From a67512c493e6aecee71ba0970457da8f20a0abc1 Mon Sep 17 00:00:00 2001 From: Phil Davis Date: Tue, 14 Apr 2020 15:15:59 +0545 Subject: [PATCH] Update icewind/smb 3.2.3 and icewind/streams 0.7.2 code --- apps/files_external/3rdparty/composer/LICENSE | 69 ++++++-- .../3rdparty/composer/autoload_classmap.php | 24 ++- .../3rdparty/composer/autoload_static.php | 24 ++- .../3rdparty/composer/installed.json | 35 ++-- .../3rdparty/icewind/smb/.editorconfig | 23 +++ .../3rdparty/icewind/smb/.gitignore | 3 + .../3rdparty/icewind/smb/.php_cs.dist | 15 ++ .../3rdparty/icewind/smb/.scrutinizer.yml | 7 + .../3rdparty/icewind/smb/README.md | 27 +++- .../3rdparty/icewind/smb/composer.json | 5 +- .../3rdparty/icewind/smb/src/ACL.php | 81 ++++++++++ .../icewind/smb/src/AbstractServer.php | 27 ++-- .../icewind/smb/src/AbstractShare.php | 2 +- .../icewind/smb/src/AnonymousAuth.php | 1 - .../3rdparty/icewind/smb/src/BasicAuth.php | 2 - .../src/Exception/AccessDeniedException.php | 3 +- .../src/Exception/AlreadyExistsException.php | 3 +- .../src/Exception/AuthenticationException.php | 3 +- .../smb/src/Exception/ConnectException.php | 3 +- .../Exception/ConnectionAbortedException.php | 11 ++ .../smb/src/Exception/ConnectionException.php | 3 +- .../Exception/ConnectionResetException.php | 11 ++ .../icewind/smb/src/Exception/Exception.php | 4 +- .../smb/src/Exception/FileInUseException.php | 3 +- .../smb/src/Exception/ForbiddenException.php | 3 +- .../Exception/InvalidArgumentException.php | 3 +- .../src/Exception/InvalidHostException.php | 3 +- .../Exception/InvalidParameterException.php | 3 +- .../src/Exception/InvalidPathException.php | 3 +- .../src/Exception/InvalidTypeException.php | 3 +- .../src/Exception/NoLoginServerException.php | 3 +- .../smb/src/Exception/NotEmptyException.php | 3 +- .../smb/src/Exception/NotFoundException.php | 3 +- .../3rdparty/icewind/smb/src/IFileInfo.php | 5 + .../icewind/smb/src/INotifyHandler.php | 1 - .../3rdparty/icewind/smb/src/IOptions.php | 29 ++++ .../3rdparty/icewind/smb/src/IServer.php | 11 +- .../3rdparty/icewind/smb/src/IShare.php | 13 ++ .../3rdparty/icewind/smb/src/ISystem.php | 78 +++++++++ .../icewind/smb/src/ITimeZoneProvider.php | 32 ++++ .../3rdparty/icewind/smb/src/KerberosAuth.php | 1 - .../icewind/smb/src/Native/NativeFileInfo.php | 64 +++++--- .../smb/src/Native/NativeReadStream.php | 9 +- .../icewind/smb/src/Native/NativeServer.php | 23 ++- .../icewind/smb/src/Native/NativeShare.php | 92 ++++++++--- .../icewind/smb/src/Native/NativeState.php | 18 ++- .../icewind/smb/src/Native/NativeStream.php | 16 +- .../smb/src/Native/NativeWriteStream.php | 20 ++- .../3rdparty/icewind/smb/src/Options.php | 35 ++++ .../icewind/smb/src/ServerFactory.php | 53 +++++-- .../3rdparty/icewind/smb/src/System.php | 56 ++++--- .../icewind/smb/src/TimeZoneProvider.php | 48 +++--- .../icewind/smb/src/Wrapped/Connection.php | 15 +- .../icewind/smb/src/Wrapped/FileInfo.php | 17 +- .../icewind/smb/src/Wrapped/NotifyHandler.php | 1 - .../icewind/smb/src/Wrapped/Parser.php | 39 +++-- .../icewind/smb/src/Wrapped/RawConnection.php | 12 -- .../icewind/smb/src/Wrapped/Server.php | 13 +- .../icewind/smb/src/Wrapped/Share.php | 149 ++++++++++++++++-- .../3rdparty/icewind/streams/.gitignore | 2 + .../3rdparty/icewind/streams/.scrutinizer.yml | 13 ++ .../3rdparty/icewind/streams/.travis.yml | 21 +-- .../3rdparty/icewind/streams/README.md | 6 +- .../3rdparty/icewind/streams/composer.json | 28 ++-- .../icewind/streams/src/CallbackWrapper.php | 48 +++--- .../icewind/streams/src/CountWrapper.php | 103 ++++++++++++ .../icewind/streams/src/Directory.php | 2 +- .../icewind/streams/src/DirectoryFilter.php | 17 +- .../icewind/streams/src/DirectoryWrapper.php | 49 +----- .../icewind/streams/src/HashWrapper.php | 80 ++++++++++ .../icewind/streams/src/IteratorDirectory.php | 38 ++--- .../icewind/streams/src/NullWrapper.php | 18 +-- .../3rdparty/icewind/streams/src/Path.php | 4 +- .../icewind/streams/src/PathWrapper.php | 6 +- .../icewind/streams/src/ReadHashWrapper.php | 40 +++++ .../icewind/streams/src/RetryWrapper.php | 22 +-- .../icewind/streams/src/SeekableWrapper.php | 23 +-- .../src/{UrlCallBack.php => UrlCallback.php} | 34 ++-- .../3rdparty/icewind/streams/src/Wrapper.php | 44 +----- .../icewind/streams/src/WrapperHandler.php | 112 +++++++++++++ .../icewind/streams/src/WriteHashWrapper.php | 37 +++++ 81 files changed, 1498 insertions(+), 515 deletions(-) create mode 100644 apps/files_external/3rdparty/icewind/smb/.editorconfig create mode 100644 apps/files_external/3rdparty/icewind/smb/.php_cs.dist create mode 100644 apps/files_external/3rdparty/icewind/smb/src/ACL.php create mode 100644 apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionAbortedException.php create mode 100644 apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionResetException.php create mode 100644 apps/files_external/3rdparty/icewind/smb/src/IOptions.php create mode 100644 apps/files_external/3rdparty/icewind/smb/src/ISystem.php create mode 100644 apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php create mode 100644 apps/files_external/3rdparty/icewind/smb/src/Options.php create mode 100644 apps/files_external/3rdparty/icewind/streams/.scrutinizer.yml create mode 100644 apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php create mode 100644 apps/files_external/3rdparty/icewind/streams/src/HashWrapper.php create mode 100644 apps/files_external/3rdparty/icewind/streams/src/ReadHashWrapper.php rename apps/files_external/3rdparty/icewind/streams/src/{UrlCallBack.php => UrlCallback.php} (79%) create mode 100644 apps/files_external/3rdparty/icewind/streams/src/WrapperHandler.php create mode 100644 apps/files_external/3rdparty/icewind/streams/src/WriteHashWrapper.php diff --git a/apps/files_external/3rdparty/composer/LICENSE b/apps/files_external/3rdparty/composer/LICENSE index f27399a042d9..f0157a6ed025 100644 --- a/apps/files_external/3rdparty/composer/LICENSE +++ b/apps/files_external/3rdparty/composer/LICENSE @@ -1,21 +1,56 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Composer +Upstream-Contact: Jordi Boggiano +Source: https://github.com/composer/composer -Copyright (c) Nils Adermann, Jordi Boggiano +Files: * +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano +License: Expat -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: +Files: src/Composer/Util/TlsHelper.php +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano + 2013, Evan Coury +License: Expat and BSD-2-Clause -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +License: BSD-2-Clause + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + . + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + . + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php index 914295203365..bc3decf0bee1 100644 --- a/apps/files_external/3rdparty/composer/autoload_classmap.php +++ b/apps/files_external/3rdparty/composer/autoload_classmap.php @@ -6,6 +6,7 @@ $baseDir = $vendorDir; return array( + 'Icewind\\SMB\\ACL' => $vendorDir . '/icewind/smb/src/ACL.php', 'Icewind\\SMB\\AbstractServer' => $vendorDir . '/icewind/smb/src/AbstractServer.php', 'Icewind\\SMB\\AbstractShare' => $vendorDir . '/icewind/smb/src/AbstractShare.php', 'Icewind\\SMB\\AnonymousAuth' => $vendorDir . '/icewind/smb/src/AnonymousAuth.php', @@ -15,8 +16,10 @@ 'Icewind\\SMB\\Exception\\AlreadyExistsException' => $vendorDir . '/icewind/smb/src/Exception/AlreadyExistsException.php', 'Icewind\\SMB\\Exception\\AuthenticationException' => $vendorDir . '/icewind/smb/src/Exception/AuthenticationException.php', 'Icewind\\SMB\\Exception\\ConnectException' => $vendorDir . '/icewind/smb/src/Exception/ConnectException.php', + 'Icewind\\SMB\\Exception\\ConnectionAbortedException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionAbortedException.php', 'Icewind\\SMB\\Exception\\ConnectionException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionException.php', 'Icewind\\SMB\\Exception\\ConnectionRefusedException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionRefusedException.php', + 'Icewind\\SMB\\Exception\\ConnectionResetException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionResetException.php', 'Icewind\\SMB\\Exception\\DependencyException' => $vendorDir . '/icewind/smb/src/Exception/DependencyException.php', 'Icewind\\SMB\\Exception\\Exception' => $vendorDir . '/icewind/smb/src/Exception/Exception.php', 'Icewind\\SMB\\Exception\\FileInUseException' => $vendorDir . '/icewind/smb/src/Exception/FileInUseException.php', @@ -39,8 +42,11 @@ 'Icewind\\SMB\\IAuth' => $vendorDir . '/icewind/smb/src/IAuth.php', 'Icewind\\SMB\\IFileInfo' => $vendorDir . '/icewind/smb/src/IFileInfo.php', 'Icewind\\SMB\\INotifyHandler' => $vendorDir . '/icewind/smb/src/INotifyHandler.php', + 'Icewind\\SMB\\IOptions' => $vendorDir . '/icewind/smb/src/IOptions.php', 'Icewind\\SMB\\IServer' => $vendorDir . '/icewind/smb/src/IServer.php', 'Icewind\\SMB\\IShare' => $vendorDir . '/icewind/smb/src/IShare.php', + 'Icewind\\SMB\\ISystem' => $vendorDir . '/icewind/smb/src/ISystem.php', + 'Icewind\\SMB\\ITimeZoneProvider' => $vendorDir . '/icewind/smb/src/ITimeZoneProvider.php', 'Icewind\\SMB\\KerberosAuth' => $vendorDir . '/icewind/smb/src/KerberosAuth.php', 'Icewind\\SMB\\Native\\NativeFileInfo' => $vendorDir . '/icewind/smb/src/Native/NativeFileInfo.php', 'Icewind\\SMB\\Native\\NativeReadStream' => $vendorDir . '/icewind/smb/src/Native/NativeReadStream.php', @@ -49,8 +55,19 @@ 'Icewind\\SMB\\Native\\NativeState' => $vendorDir . '/icewind/smb/src/Native/NativeState.php', 'Icewind\\SMB\\Native\\NativeStream' => $vendorDir . '/icewind/smb/src/Native/NativeStream.php', 'Icewind\\SMB\\Native\\NativeWriteStream' => $vendorDir . '/icewind/smb/src/Native/NativeWriteStream.php', + 'Icewind\\SMB\\Options' => $vendorDir . '/icewind/smb/src/Options.php', 'Icewind\\SMB\\ServerFactory' => $vendorDir . '/icewind/smb/src/ServerFactory.php', 'Icewind\\SMB\\System' => $vendorDir . '/icewind/smb/src/System.php', + 'Icewind\\SMB\\Test\\AbstractShareTest' => $vendorDir . '/icewind/smb/tests/AbstractShareTest.php', + 'Icewind\\SMB\\Test\\NativeShareTest' => $vendorDir . '/icewind/smb/tests/NativeShareTest.php', + 'Icewind\\SMB\\Test\\NativeStreamTest' => $vendorDir . '/icewind/smb/tests/NativeStreamTest.php', + 'Icewind\\SMB\\Test\\NotifyHandlerTest' => $vendorDir . '/icewind/smb/tests/NotifyHandlerTest.php', + 'Icewind\\SMB\\Test\\ParserTest' => $vendorDir . '/icewind/smb/tests/ParserTest.php', + 'Icewind\\SMB\\Test\\ServerFactoryTest' => $vendorDir . '/icewind/smb/tests/ServerFactoryTest.php', + 'Icewind\\SMB\\Test\\ServerTest' => $vendorDir . '/icewind/smb/tests/ServerTest.php', + 'Icewind\\SMB\\Test\\ShareTest' => $vendorDir . '/icewind/smb/tests/ShareTest.php', + 'Icewind\\SMB\\Test\\TestCase' => $vendorDir . '/icewind/smb/tests/TestCase.php', + 'Icewind\\SMB\\Test\\TimeZoneProviderTest' => $vendorDir . '/icewind/smb/tests/TimeZoneProviderTest.php', 'Icewind\\SMB\\TimeZoneProvider' => $vendorDir . '/icewind/smb/src/TimeZoneProvider.php', 'Icewind\\SMB\\Wrapped\\Connection' => $vendorDir . '/icewind/smb/src/Wrapped/Connection.php', 'Icewind\\SMB\\Wrapped\\ErrorCodes' => $vendorDir . '/icewind/smb/src/Wrapped/ErrorCodes.php', @@ -61,17 +78,22 @@ 'Icewind\\SMB\\Wrapped\\Server' => $vendorDir . '/icewind/smb/src/Wrapped/Server.php', 'Icewind\\SMB\\Wrapped\\Share' => $vendorDir . '/icewind/smb/src/Wrapped/Share.php', 'Icewind\\Streams\\CallbackWrapper' => $vendorDir . '/icewind/streams/src/CallbackWrapper.php', + 'Icewind\\Streams\\CountWrapper' => $vendorDir . '/icewind/streams/src/CountWrapper.php', 'Icewind\\Streams\\Directory' => $vendorDir . '/icewind/streams/src/Directory.php', 'Icewind\\Streams\\DirectoryFilter' => $vendorDir . '/icewind/streams/src/DirectoryFilter.php', 'Icewind\\Streams\\DirectoryWrapper' => $vendorDir . '/icewind/streams/src/DirectoryWrapper.php', 'Icewind\\Streams\\File' => $vendorDir . '/icewind/streams/src/File.php', + 'Icewind\\Streams\\HashWrapper' => $vendorDir . '/icewind/streams/src/HashWrapper.php', 'Icewind\\Streams\\IteratorDirectory' => $vendorDir . '/icewind/streams/src/IteratorDirectory.php', 'Icewind\\Streams\\NullWrapper' => $vendorDir . '/icewind/streams/src/NullWrapper.php', 'Icewind\\Streams\\Path' => $vendorDir . '/icewind/streams/src/Path.php', 'Icewind\\Streams\\PathWrapper' => $vendorDir . '/icewind/streams/src/PathWrapper.php', + 'Icewind\\Streams\\ReadHashWrapper' => $vendorDir . '/icewind/streams/src/ReadHashWrapper.php', 'Icewind\\Streams\\RetryWrapper' => $vendorDir . '/icewind/streams/src/RetryWrapper.php', 'Icewind\\Streams\\SeekableWrapper' => $vendorDir . '/icewind/streams/src/SeekableWrapper.php', 'Icewind\\Streams\\Url' => $vendorDir . '/icewind/streams/src/Url.php', - 'Icewind\\Streams\\UrlCallback' => $vendorDir . '/icewind/streams/src/UrlCallBack.php', + 'Icewind\\Streams\\UrlCallback' => $vendorDir . '/icewind/streams/src/UrlCallback.php', 'Icewind\\Streams\\Wrapper' => $vendorDir . '/icewind/streams/src/Wrapper.php', + 'Icewind\\Streams\\WrapperHandler' => $vendorDir . '/icewind/streams/src/WrapperHandler.php', + 'Icewind\\Streams\\WriteHashWrapper' => $vendorDir . '/icewind/streams/src/WriteHashWrapper.php', ); diff --git a/apps/files_external/3rdparty/composer/autoload_static.php b/apps/files_external/3rdparty/composer/autoload_static.php index c7080c376320..4001f1e630ea 100644 --- a/apps/files_external/3rdparty/composer/autoload_static.php +++ b/apps/files_external/3rdparty/composer/autoload_static.php @@ -35,6 +35,7 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3 ); public static $classMap = array ( + 'Icewind\\SMB\\ACL' => __DIR__ . '/..' . '/icewind/smb/src/ACL.php', 'Icewind\\SMB\\AbstractServer' => __DIR__ . '/..' . '/icewind/smb/src/AbstractServer.php', 'Icewind\\SMB\\AbstractShare' => __DIR__ . '/..' . '/icewind/smb/src/AbstractShare.php', 'Icewind\\SMB\\AnonymousAuth' => __DIR__ . '/..' . '/icewind/smb/src/AnonymousAuth.php', @@ -44,8 +45,10 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3 'Icewind\\SMB\\Exception\\AlreadyExistsException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/AlreadyExistsException.php', 'Icewind\\SMB\\Exception\\AuthenticationException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/AuthenticationException.php', 'Icewind\\SMB\\Exception\\ConnectException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectException.php', + 'Icewind\\SMB\\Exception\\ConnectionAbortedException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectionAbortedException.php', 'Icewind\\SMB\\Exception\\ConnectionException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectionException.php', 'Icewind\\SMB\\Exception\\ConnectionRefusedException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectionRefusedException.php', + 'Icewind\\SMB\\Exception\\ConnectionResetException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectionResetException.php', 'Icewind\\SMB\\Exception\\DependencyException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/DependencyException.php', 'Icewind\\SMB\\Exception\\Exception' => __DIR__ . '/..' . '/icewind/smb/src/Exception/Exception.php', 'Icewind\\SMB\\Exception\\FileInUseException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/FileInUseException.php', @@ -68,8 +71,11 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3 'Icewind\\SMB\\IAuth' => __DIR__ . '/..' . '/icewind/smb/src/IAuth.php', 'Icewind\\SMB\\IFileInfo' => __DIR__ . '/..' . '/icewind/smb/src/IFileInfo.php', 'Icewind\\SMB\\INotifyHandler' => __DIR__ . '/..' . '/icewind/smb/src/INotifyHandler.php', + 'Icewind\\SMB\\IOptions' => __DIR__ . '/..' . '/icewind/smb/src/IOptions.php', 'Icewind\\SMB\\IServer' => __DIR__ . '/..' . '/icewind/smb/src/IServer.php', 'Icewind\\SMB\\IShare' => __DIR__ . '/..' . '/icewind/smb/src/IShare.php', + 'Icewind\\SMB\\ISystem' => __DIR__ . '/..' . '/icewind/smb/src/ISystem.php', + 'Icewind\\SMB\\ITimeZoneProvider' => __DIR__ . '/..' . '/icewind/smb/src/ITimeZoneProvider.php', 'Icewind\\SMB\\KerberosAuth' => __DIR__ . '/..' . '/icewind/smb/src/KerberosAuth.php', 'Icewind\\SMB\\Native\\NativeFileInfo' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeFileInfo.php', 'Icewind\\SMB\\Native\\NativeReadStream' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeReadStream.php', @@ -78,8 +84,19 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3 'Icewind\\SMB\\Native\\NativeState' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeState.php', 'Icewind\\SMB\\Native\\NativeStream' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeStream.php', 'Icewind\\SMB\\Native\\NativeWriteStream' => __DIR__ . '/..' . '/icewind/smb/src/Native/NativeWriteStream.php', + 'Icewind\\SMB\\Options' => __DIR__ . '/..' . '/icewind/smb/src/Options.php', 'Icewind\\SMB\\ServerFactory' => __DIR__ . '/..' . '/icewind/smb/src/ServerFactory.php', 'Icewind\\SMB\\System' => __DIR__ . '/..' . '/icewind/smb/src/System.php', + 'Icewind\\SMB\\Test\\AbstractShareTest' => __DIR__ . '/..' . '/icewind/smb/tests/AbstractShareTest.php', + 'Icewind\\SMB\\Test\\NativeShareTest' => __DIR__ . '/..' . '/icewind/smb/tests/NativeShareTest.php', + 'Icewind\\SMB\\Test\\NativeStreamTest' => __DIR__ . '/..' . '/icewind/smb/tests/NativeStreamTest.php', + 'Icewind\\SMB\\Test\\NotifyHandlerTest' => __DIR__ . '/..' . '/icewind/smb/tests/NotifyHandlerTest.php', + 'Icewind\\SMB\\Test\\ParserTest' => __DIR__ . '/..' . '/icewind/smb/tests/ParserTest.php', + 'Icewind\\SMB\\Test\\ServerFactoryTest' => __DIR__ . '/..' . '/icewind/smb/tests/ServerFactoryTest.php', + 'Icewind\\SMB\\Test\\ServerTest' => __DIR__ . '/..' . '/icewind/smb/tests/ServerTest.php', + 'Icewind\\SMB\\Test\\ShareTest' => __DIR__ . '/..' . '/icewind/smb/tests/ShareTest.php', + 'Icewind\\SMB\\Test\\TestCase' => __DIR__ . '/..' . '/icewind/smb/tests/TestCase.php', + 'Icewind\\SMB\\Test\\TimeZoneProviderTest' => __DIR__ . '/..' . '/icewind/smb/tests/TimeZoneProviderTest.php', 'Icewind\\SMB\\TimeZoneProvider' => __DIR__ . '/..' . '/icewind/smb/src/TimeZoneProvider.php', 'Icewind\\SMB\\Wrapped\\Connection' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Connection.php', 'Icewind\\SMB\\Wrapped\\ErrorCodes' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/ErrorCodes.php', @@ -90,19 +107,24 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3 'Icewind\\SMB\\Wrapped\\Server' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Server.php', 'Icewind\\SMB\\Wrapped\\Share' => __DIR__ . '/..' . '/icewind/smb/src/Wrapped/Share.php', 'Icewind\\Streams\\CallbackWrapper' => __DIR__ . '/..' . '/icewind/streams/src/CallbackWrapper.php', + 'Icewind\\Streams\\CountWrapper' => __DIR__ . '/..' . '/icewind/streams/src/CountWrapper.php', 'Icewind\\Streams\\Directory' => __DIR__ . '/..' . '/icewind/streams/src/Directory.php', 'Icewind\\Streams\\DirectoryFilter' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryFilter.php', 'Icewind\\Streams\\DirectoryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/DirectoryWrapper.php', 'Icewind\\Streams\\File' => __DIR__ . '/..' . '/icewind/streams/src/File.php', + 'Icewind\\Streams\\HashWrapper' => __DIR__ . '/..' . '/icewind/streams/src/HashWrapper.php', 'Icewind\\Streams\\IteratorDirectory' => __DIR__ . '/..' . '/icewind/streams/src/IteratorDirectory.php', 'Icewind\\Streams\\NullWrapper' => __DIR__ . '/..' . '/icewind/streams/src/NullWrapper.php', 'Icewind\\Streams\\Path' => __DIR__ . '/..' . '/icewind/streams/src/Path.php', 'Icewind\\Streams\\PathWrapper' => __DIR__ . '/..' . '/icewind/streams/src/PathWrapper.php', + 'Icewind\\Streams\\ReadHashWrapper' => __DIR__ . '/..' . '/icewind/streams/src/ReadHashWrapper.php', 'Icewind\\Streams\\RetryWrapper' => __DIR__ . '/..' . '/icewind/streams/src/RetryWrapper.php', 'Icewind\\Streams\\SeekableWrapper' => __DIR__ . '/..' . '/icewind/streams/src/SeekableWrapper.php', 'Icewind\\Streams\\Url' => __DIR__ . '/..' . '/icewind/streams/src/Url.php', - 'Icewind\\Streams\\UrlCallback' => __DIR__ . '/..' . '/icewind/streams/src/UrlCallBack.php', + 'Icewind\\Streams\\UrlCallback' => __DIR__ . '/..' . '/icewind/streams/src/UrlCallback.php', 'Icewind\\Streams\\Wrapper' => __DIR__ . '/..' . '/icewind/streams/src/Wrapper.php', + 'Icewind\\Streams\\WrapperHandler' => __DIR__ . '/..' . '/icewind/streams/src/WrapperHandler.php', + 'Icewind\\Streams\\WriteHashWrapper' => __DIR__ . '/..' . '/icewind/streams/src/WriteHashWrapper.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json index 3ad23983829d..9574fb79655c 100644 --- a/apps/files_external/3rdparty/composer/installed.json +++ b/apps/files_external/3rdparty/composer/installed.json @@ -1,27 +1,28 @@ [ { "name": "icewind/smb", - "version": "v3.0.0", - "version_normalized": "3.0.0.0", + "version": "v3.2.3", + "version_normalized": "3.2.3.0", "source": { "type": "git", "url": "https://github.com/icewind1991/SMB.git", - "reference": "0d31da4757a37d322e1e181f2286e8a4c89fbc0c" + "reference": "db50bb51bd0a0e55506e82cf439a9ecd232f64d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/icewind1991/SMB/zipball/0d31da4757a37d322e1e181f2286e8a4c89fbc0c", - "reference": "0d31da4757a37d322e1e181f2286e8a4c89fbc0c", + "url": "https://api.github.com/repos/icewind1991/SMB/zipball/db50bb51bd0a0e55506e82cf439a9ecd232f64d4", + "reference": "db50bb51bd0a0e55506e82cf439a9ecd232f64d4", "shasum": "" }, "require": { "icewind/streams": ">=0.2.0", - "php": ">=5.6" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^5.7" + "friendsofphp/php-cs-fixer": "^2.13", + "phpunit/phpunit": "^7.0" }, - "time": "2018-05-24T09:48:51+00:00", + "time": "2020-04-08T15:20:22+00:00", "type": "library", "installation-source": "source", "autoload": { @@ -44,27 +45,27 @@ }, { "name": "icewind/streams", - "version": "0.5.2", - "version_normalized": "0.5.2.0", + "version": "v0.7.2", + "version_normalized": "0.7.2.0", "source": { "type": "git", "url": "https://github.com/icewind1991/Streams.git", - "reference": "6bfd2fdbd99319f5e010d0a684409189a562cb1e" + "reference": "77d750ccc654c0eda4a41fedb2dbd71053755790" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/icewind1991/Streams/zipball/6bfd2fdbd99319f5e010d0a684409189a562cb1e", - "reference": "6bfd2fdbd99319f5e010d0a684409189a562cb1e", + "url": "https://api.github.com/repos/icewind1991/Streams/zipball/77d750ccc654c0eda4a41fedb2dbd71053755790", + "reference": "77d750ccc654c0eda4a41fedb2dbd71053755790", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "^4.8", - "satooshi/php-coveralls": "v1.0.0" + "php-coveralls/php-coveralls": "v2.1.0", + "phpunit/phpunit": "^5.7" }, - "time": "2016-12-02T14:21:23+00:00", + "time": "2020-04-08T14:59:33+00:00", "type": "library", "installation-source": "dist", "autoload": { diff --git a/apps/files_external/3rdparty/icewind/smb/.editorconfig b/apps/files_external/3rdparty/icewind/smb/.editorconfig new file mode 100644 index 000000000000..4afdf82f3d09 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/.editorconfig @@ -0,0 +1,23 @@ +[*] +charset=utf-8 +end_of_line=lf +insert_final_newline=false +indent_style=space +indent_size=4 + +[{composer.lock,.babelrc,.stylelintrc,.eslintrc,jest.config,*.bowerrc,*.jsb3,*.jsb2,*.json}] +indent_style=space +indent_size=2 + +[{Makefile.*,Makefile,GNUmakefile,makefile,*.mk}] +indent_style=tab +tab_width=4 + +[{*.module,*.hphp,*.phtml,*.php5,*.php4,*.php,*.inc}] +indent_style=tab +tab_width=4 + +[{*.yml,*.yaml}] +indent_style=space +indent_size=2 + diff --git a/apps/files_external/3rdparty/icewind/smb/.gitignore b/apps/files_external/3rdparty/icewind/smb/.gitignore index 4f389129e2d9..17e19f04f56c 100644 --- a/apps/files_external/3rdparty/icewind/smb/.gitignore +++ b/apps/files_external/3rdparty/icewind/smb/.gitignore @@ -1,3 +1,6 @@ .idea vendor composer.lock +.php_cs.cache +listen.php +test.php diff --git a/apps/files_external/3rdparty/icewind/smb/.php_cs.dist b/apps/files_external/3rdparty/icewind/smb/.php_cs.dist new file mode 100644 index 000000000000..a2fdf19e8022 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/.php_cs.dist @@ -0,0 +1,15 @@ +exclude('vendor') + ->in(__DIR__) +; +return PhpCsFixer\Config::create() + ->setRules([ + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'braces' => ['position_after_functions_and_oop_constructs' => 'same'], + 'binary_operator_spaces' => ['align_double_arrow' => true, 'align_equals' => false], + ]) + ->setIndent("\t") + ->setFinder($finder) + ; diff --git a/apps/files_external/3rdparty/icewind/smb/.scrutinizer.yml b/apps/files_external/3rdparty/icewind/smb/.scrutinizer.yml index 18a8d125139e..810cafb122b9 100644 --- a/apps/files_external/3rdparty/icewind/smb/.scrutinizer.yml +++ b/apps/files_external/3rdparty/icewind/smb/.scrutinizer.yml @@ -8,3 +8,10 @@ tools: filter: excluded_paths: - 'tests/*' + +build: + nodes: + analysis: + tests: + override: + - php-scrutinizer-run \ No newline at end of file diff --git a/apps/files_external/3rdparty/icewind/smb/README.md b/apps/files_external/3rdparty/icewind/smb/README.md index fd47f1a43939..6a35e736acbb 100644 --- a/apps/files_external/3rdparty/icewind/smb/README.md +++ b/apps/files_external/3rdparty/icewind/smb/README.md @@ -26,7 +26,7 @@ use Icewind\SMB\BasicAuth; require('vendor/autoload.php'); $serverFactory = new ServerFactory(); -$auth = new BasicAuth('test', 'workgroup', 'test'); +$auth = new BasicAuth('user', 'workgroup', 'password'); $server = $serverFactory->createServer('localhost', $auth); $share = $server->getShare('test'); @@ -102,6 +102,15 @@ fwrite($fh, 'bar'); fclose($fh); ``` +**Note**: write() will truncate your file to 0bytes. You may open a writeable stream with append() which will point +the cursor to the end of the file or create it if it does not exists yet. (append() is only compatible with libsmbclient-php) +```php +$fh = $share->append('test.txt'); +fwrite($fh, 'bar'); +fclose($fh); +``` + + ### Using notify ```php @@ -110,6 +119,22 @@ $share->notify('')->listen(function (\Icewind\SMB\Change $change) { }); ``` +### Changing network timeouts + +```php +$options = new Options(); +$options->setTimeout(5); +$serverFactory = new ServerFactory($options); +``` + +### Customizing system integration + +The `smbclient` backend needs to get various information about the system it's running on to function +such as the paths of various binaries or the system timezone. +While the default logic for getting this information should work on most systems, it possible to customize this behaviour. + +In order to customize the integration you provide a custom implementation of `ITimezoneProvider` and/or `ISystem` and pass them as arguments to the `ServerFactory`. + ## Testing SMB Use the following steps to check if the library can connect to your SMB share. diff --git a/apps/files_external/3rdparty/icewind/smb/composer.json b/apps/files_external/3rdparty/icewind/smb/composer.json index 708c59bc7251..8ec551c7340f 100644 --- a/apps/files_external/3rdparty/icewind/smb/composer.json +++ b/apps/files_external/3rdparty/icewind/smb/composer.json @@ -9,11 +9,12 @@ } ], "require" : { - "php": ">=5.6", + "php": ">=7.1", "icewind/streams": ">=0.2.0" }, "require-dev": { - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^7.0", + "friendsofphp/php-cs-fixer": "^2.13" }, "autoload" : { "psr-4": { diff --git a/apps/files_external/3rdparty/icewind/smb/src/ACL.php b/apps/files_external/3rdparty/icewind/smb/src/ACL.php new file mode 100644 index 000000000000..bdb77257f179 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/ACL.php @@ -0,0 +1,81 @@ + + * + * @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 . + * + */ + +namespace Icewind\SMB; + +class ACL { + const TYPE_ALLOW = 0; + const TYPE_DENY = 1; + + const MASK_READ = 0x0001; + const MASK_WRITE = 0x0002; + const MASK_EXECUTE = 0x00020; + const MASK_DELETE = 0x10000; + + const FLAG_OBJECT_INHERIT = 0x1; + const FLAG_CONTAINER_INHERIT = 0x2; + + private $type; + private $flags; + private $mask; + + public function __construct(int $type, int $flags, int $mask) { + $this->type = $type; + $this->flags = $flags; + $this->mask = $mask; + } + + /** + * Check if the acl allows a specific permissions + * + * Note that this does not take inherited acls into account + * + * @param int $mask one of the ACL::MASK_* constants + * @return bool + */ + public function allows(int $mask): bool { + return $this->type === self::TYPE_ALLOW && ($this->mask & $mask) === $mask; + } + + /** + * Check if the acl allows a specific permissions + * + * Note that this does not take inherited acls into account + * + * @param int $mask one of the ACL::MASK_* constants + * @return bool + */ + public function denies(int $mask): bool { + return $this->type === self::TYPE_DENY && ($this->mask & $mask) === $mask; + } + + public function getType(): int { + return $this->type; + } + + public function getFlags(): int { + return $this->flags; + } + + public function getMask(): int { + return $this->mask; + } +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php b/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php index 7fa87a595730..aa2adfa67b37 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php +++ b/apps/files_external/3rdparty/icewind/smb/src/AbstractServer.php @@ -21,7 +21,6 @@ namespace Icewind\SMB; - abstract class AbstractServer implements IServer { const LOCALE = 'en_US.UTF-8'; @@ -36,7 +35,7 @@ abstract class AbstractServer implements IServer { protected $auth; /** - * @var \Icewind\SMB\System + * @var ISystem */ protected $system; @@ -45,41 +44,41 @@ abstract class AbstractServer implements IServer { */ protected $timezoneProvider; + /** @var IOptions */ + protected $options; + /** * @param string $host * @param IAuth $auth - * @param System $system + * @param ISystem $system * @param TimeZoneProvider $timeZoneProvider + * @param IOptions $options */ - public function __construct($host, IAuth $auth, System $system, TimeZoneProvider $timeZoneProvider) { + public function __construct($host, IAuth $auth, ISystem $system, TimeZoneProvider $timeZoneProvider, IOptions $options) { $this->host = $host; $this->auth = $auth; $this->system = $system; $this->timezoneProvider = $timeZoneProvider; + $this->options = $options; } - /** - * @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(); + return $this->timezoneProvider->get($this->host); } public function getSystem() { return $this->system; } + + public function getOptions() { + return $this->options; + } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php b/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php index 0af03ff56988..b53c253be08e 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php +++ b/apps/files_external/3rdparty/icewind/smb/src/AbstractShare.php @@ -13,7 +13,7 @@ abstract class AbstractShare implements IShare { private $forbiddenCharacters; public function __construct() { - $this->forbiddenCharacters = array('?', '<', '>', ':', '*', '|', '"', chr(0), "\n", "\r"); + $this->forbiddenCharacters = ['?', '<', '>', ':', '*', '|', '"', chr(0), "\n", "\r"]; } protected function verifyPath($path) { diff --git a/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php b/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php index 6d1feacf1ee1..737cc7c63f19 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php +++ b/apps/files_external/3rdparty/icewind/smb/src/AnonymousAuth.php @@ -21,7 +21,6 @@ namespace Icewind\SMB; - class AnonymousAuth implements IAuth { public function getUsername() { return null; diff --git a/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php b/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php index 0032dc53034d..9d7f9b5d3064 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php +++ b/apps/files_external/3rdparty/icewind/smb/src/BasicAuth.php @@ -21,7 +21,6 @@ namespace Icewind\SMB; - class BasicAuth implements IAuth { /** @var string */ private $username; @@ -62,5 +61,4 @@ public function getExtraCommandLineArguments() { public function setExtraSmbClientOptions($smbClientState) { // noop } - } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php index 4b7d22b35407..adc42344b436 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class AccessDeniedException extends ConnectException {} +class AccessDeniedException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php index 4636b9d17867..aaa5226f795a 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class AlreadyExistsException extends InvalidRequestException {} +class AlreadyExistsException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php index ddf5d7e34dc6..9626d795e343 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class AuthenticationException extends ConnectException{} +class AuthenticationException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php index 310d441bf5c0..9aa174ba5bde 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class ConnectException extends Exception {} +class ConnectException extends Exception { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionAbortedException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionAbortedException.php new file mode 100644 index 000000000000..59363ca7ba90 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionAbortedException.php @@ -0,0 +1,11 @@ + + * This file is licensed under the Licensed under the MIT license: + * http://opensource.org/licenses/MIT + */ + +namespace Icewind\SMB\Exception; + +class ConnectionAbortedException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php index 21033560fc05..d27752e702b3 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class ConnectionException extends ConnectException {} +class ConnectionException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionResetException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionResetException.php new file mode 100644 index 000000000000..d5ac10d32dc4 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionResetException.php @@ -0,0 +1,11 @@ + + * This file is licensed under the Licensed under the MIT license: + * http://opensource.org/licenses/MIT + */ + +namespace Icewind\SMB\Exception; + +class ConnectionResetException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php index 93f2c1b3e2e1..4954518f9800 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php @@ -8,7 +8,7 @@ namespace Icewind\SMB\Exception; class Exception extends \Exception { - static public function unknown($path, $error) { + public static function unknown($path, $error) { $message = 'Unknown error (' . $error . ')'; if ($path) { $message .= ' for ' . $path; @@ -23,7 +23,7 @@ static public function unknown($path, $error) { * @param string $path * @return Exception */ - static public function fromMap(array $exceptionMap, $error, $path) { + public static function fromMap(array $exceptionMap, $error, $path) { if (isset($exceptionMap[$error])) { $exceptionClass = $exceptionMap[$error]; if (is_numeric($error)) { diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php index 46460eb6936c..4408d39e06e3 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class FileInUseException extends InvalidRequestException {} +class FileInUseException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php index 117d6a438ea0..31c051893e89 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class ForbiddenException extends InvalidRequestException {} +class ForbiddenException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidArgumentException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidArgumentException.php index f12bb3a34895..a21d069d47fc 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidArgumentException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidArgumentException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class InvalidArgumentException extends InvalidRequestException {} +class InvalidArgumentException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php index 4b17f1a4de60..2358b7f338f0 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class InvalidHostException extends ConnectException {} +class InvalidHostException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidParameterException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidParameterException.php index 163b571183d8..5ffbf4f3819f 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidParameterException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidParameterException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class InvalidParameterException extends InvalidRequestException {} +class InvalidParameterException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidPathException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidPathException.php index 4bba74f269f3..2b7859de155f 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidPathException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidPathException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class InvalidPathException extends InvalidRequestException {} +class InvalidPathException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php index 63b79305ad42..00da288b8a19 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class InvalidTypeException extends InvalidRequestException {} +class InvalidTypeException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NoLoginServerException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NoLoginServerException.php index 43f7f9aeff9e..8f0c5539282e 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/NoLoginServerException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/NoLoginServerException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class NoLoginServerException extends ConnectException {} +class NoLoginServerException extends ConnectException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php index 789a76bcb9ee..0e606d65ca3b 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class NotEmptyException extends InvalidRequestException {} +class NotEmptyException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php index 9ce97cd535b9..29ea2d87c99c 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php @@ -7,4 +7,5 @@ namespace Icewind\SMB\Exception; -class NotFoundException extends InvalidRequestException {} +class NotFoundException extends InvalidRequestException { +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php index ae8acd3a3dba..3411d498d787 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php +++ b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php @@ -65,4 +65,9 @@ public function isSystem(); * @return bool */ public function isArchived(); + + /** + * @return ACL[] + */ + public function getAcls(): array; } diff --git a/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php index 1ee59b26ddd4..c3ee3ffe8cf8 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php +++ b/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php @@ -8,7 +8,6 @@ namespace Icewind\SMB; - interface INotifyHandler { // https://msdn.microsoft.com/en-us/library/dn392331.aspx const NOTIFY_ADDED = 1; diff --git a/apps/files_external/3rdparty/icewind/smb/src/IOptions.php b/apps/files_external/3rdparty/icewind/smb/src/IOptions.php new file mode 100644 index 000000000000..c46d2c8b3dc2 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/IOptions.php @@ -0,0 +1,29 @@ + + * + * @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 . + * + */ + +namespace Icewind\SMB; + +interface IOptions { + /** + * @return int + */ + public function getTimeout(); +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/IServer.php b/apps/files_external/3rdparty/icewind/smb/src/IServer.php index 2c8d5c67de29..0b832025aabe 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/IServer.php +++ b/apps/files_external/3rdparty/icewind/smb/src/IServer.php @@ -52,13 +52,18 @@ public function getShare($name); public function getTimeZone(); /** - * @return System + * @return ISystem */ public function getSystem(); /** - * @param System $system + * @return IOptions + */ + public function getOptions(); + + /** + * @param ISystem $system * @return bool */ - public static function available(System $system); + public static function available(ISystem $system); } diff --git a/apps/files_external/3rdparty/icewind/smb/src/IShare.php b/apps/files_external/3rdparty/icewind/smb/src/IShare.php index 8f6d5058b81a..92a12b46f2b9 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/IShare.php +++ b/apps/files_external/3rdparty/icewind/smb/src/IShare.php @@ -52,6 +52,7 @@ public function read($source); /** * Open a writable stream to a remote file + * Note: This method will truncate the file to 0bytes * * @param string $target * @return resource a write only stream to upload a remote file @@ -61,6 +62,18 @@ public function read($source); */ public function write($target); + /** + * Open a writable stream to a remote file and set the cursor to the end of the file + * + * @param string $target + * @return resource a write only stream to upload a remote file + * + * @throws \Icewind\SMB\Exception\NotFoundException + * @throws \Icewind\SMB\Exception\InvalidTypeException + * @throws \Icewind\SMB\Exception\InvalidRequestException + */ + public function append($target); + /** * Rename a remote file * diff --git a/apps/files_external/3rdparty/icewind/smb/src/ISystem.php b/apps/files_external/3rdparty/icewind/smb/src/ISystem.php new file mode 100644 index 000000000000..099946107164 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/ISystem.php @@ -0,0 +1,78 @@ + + * + * @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 . + * + */ + +namespace Icewind\SMB; + +/** + * The `ISystem` interface provides a way to access system dependent information + * such as the availability and location of certain binaries. + */ +interface ISystem { + /** + * Get the path to a file descriptor of the current process + * + * @param int $num the file descriptor id + * @return string + */ + public function getFD($num); + + /** + * Get the full path to the `smbclient` binary of false if the binary is not available + * + * @return string|bool + */ + public function getSmbclientPath(); + + /** + * Get the full path to the `net` binary of false if the binary is not available + * + * @return string|bool + */ + public function getNetPath(); + + /** + * Get the full path to the `smbcacls` binary of false if the binary is not available + * + * @return string|bool + */ + public function getSmbcAclsPath(); + + /** + * Get the full path to the `stdbuf` binary of false if the binary is not available + * + * @return string|bool + */ + public function getStdBufPath(); + + /** + * Get the full path to the `date` binary of false if the binary is not available + * + * @return string|bool + */ + public function getDatePath(); + + /** + * Whether or not the smbclient php extension is enabled + * + * @return bool + */ + public function libSmbclientAvailable(); +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php b/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php new file mode 100644 index 000000000000..56e09ffb3921 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/ITimeZoneProvider.php @@ -0,0 +1,32 @@ + + * + * @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 . + * + */ + +namespace Icewind\SMB; + +interface ITimeZoneProvider { + /** + * Get the timezone of the smb server + * + * @param string $host + * @return string + */ + public function get($host); +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php b/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php index 9510a6dc277b..0e91202cb763 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php +++ b/apps/files_external/3rdparty/icewind/smb/src/KerberosAuth.php @@ -45,5 +45,4 @@ public function setExtraSmbClientOptions($smbClientState) { smbclient_option_set($smbClientState, SMBCLIENT_OPT_USE_KERBEROS, true); smbclient_option_set($smbClientState, SMBCLIENT_OPT_FALLBACK_AFTER_KERBEROS, false); } - } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php index 3466797e21b5..24344e6f0df6 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeFileInfo.php @@ -7,11 +7,10 @@ namespace Icewind\SMB\Native; +use Icewind\SMB\ACL; use Icewind\SMB\IFileInfo; class NativeFileInfo implements IFileInfo { - const MODE_FILE = 0100000; - /** * @var string */ @@ -30,7 +29,7 @@ class NativeFileInfo implements IFileInfo { /** * @var array|null */ - protected $statCache; + protected $attributeCache = null; /** * @var int @@ -41,13 +40,11 @@ class NativeFileInfo implements IFileInfo { * @param NativeShare $share * @param string $path * @param string $name - * @param array $stat */ - public function __construct($share, $path, $name, $stat = null) { + public function __construct($share, $path, $name) { $this->share = $share; $this->path = $path; $this->name = $name; - $this->statCache = $stat; } /** @@ -68,10 +65,20 @@ public function getName() { * @return array */ protected function stat() { - if (is_null($this->statCache)) { - $this->statCache = $this->share->getStat($this->getPath()); + if (is_null($this->attributeCache)) { + $rawAttributes = explode(',', $this->share->getAttribute($this->path, 'system.dos_attr.*')); + $this->attributeCache = []; + foreach ($rawAttributes as $rawAttribute) { + [$name, $value] = explode(':', $rawAttribute); + $name = strtolower($name); + if ($name == 'mode') { + $this->attributeCache[$name] = (int)hexdec(substr($value, 2)); + } else { + $this->attributeCache[$name] = (int)$value; + } + } } - return $this->statCache; + return $this->attributeCache; } /** @@ -87,27 +94,22 @@ public function getSize() { */ public function getMTime() { $stat = $this->stat(); - return $stat['mtime']; + return $stat['change_time']; } /** - * @return bool + * @return int */ - public function isDirectory() { - $stat = $this->stat(); - return !($stat['mode'] & self::MODE_FILE); + protected function getMode() { + return $this->stat()['mode']; } /** - * @return int + * @return bool */ - protected function getMode() { - if (!$this->modeCache) { - $attribute = $this->share->getAttribute($this->path, 'system.dos_attr.mode'); - // parse hex string - $this->modeCache = (int)hexdec(substr($attribute, 2)); - } - return $this->modeCache; + public function isDirectory() { + $mode = $this->getMode(); + return (bool)($mode & IFileInfo::MODE_DIRECTORY); } /** @@ -141,4 +143,22 @@ public function isArchived() { $mode = $this->getMode(); return (bool)($mode & IFileInfo::MODE_ARCHIVE); } + + /** + * @return ACL[] + */ + public function getAcls(): array { + $acls = []; + $attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+'); + + foreach (explode(',', $attribute) as $acl) { + [$user, $permissions] = explode(':', $acl, 2); + [$type, $flags, $mask] = explode('/', $permissions); + $mask = hexdec($mask); + + $acls[$user] = new ACL($type, $flags, $mask); + } + + return $acls; + } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php index 3ef5b21639f9..fe0af760d3fb 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeReadStream.php @@ -25,7 +25,6 @@ public function stream_open($path, $mode, $options, &$opened_path) { $this->readBuffer = fopen('php://memory', 'r+'); return parent::stream_open($path, $mode, $options, $opened_path); - } /** @@ -39,13 +38,13 @@ public function stream_open($path, $mode, $options, &$opened_path) { */ public static function wrap($state, $smbStream, $mode, $url) { stream_wrapper_register('nativesmb', NativeReadStream::class); - $context = stream_context_create(array( - 'nativesmb' => array( + $context = stream_context_create([ + 'nativesmb' => [ 'state' => $state, 'handle' => $smbStream, 'url' => $url - ) - )); + ] + ]); $fh = fopen('nativesmb://', $mode, false, $context); stream_wrapper_unregister('nativesmb'); return $fh; diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php index c6274e59b5f4..aadb05d0feab 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeServer.php @@ -9,7 +9,8 @@ use Icewind\SMB\AbstractServer; use Icewind\SMB\IAuth; -use Icewind\SMB\System; +use Icewind\SMB\IOptions; +use Icewind\SMB\ISystem; use Icewind\SMB\TimeZoneProvider; class NativeServer extends AbstractServer { @@ -18,19 +19,13 @@ class NativeServer extends AbstractServer { */ protected $state; - /** - * @param string $host - * @param IAuth $auth - * @param System $system - * @param TimeZoneProvider $timeZoneProvider - */ - public function __construct($host, IAuth $auth, System $system, TimeZoneProvider $timeZoneProvider) { - parent::__construct($host, $auth, $system, $timeZoneProvider); + public function __construct($host, IAuth $auth, ISystem $system, TimeZoneProvider $timeZoneProvider, IOptions $options) { + parent::__construct($host, $auth, $system, $timeZoneProvider, $options); $this->state = new NativeState(); } protected function connect() { - $this->state->init($this->getAuth()); + $this->state->init($this->getAuth(), $this->getOptions()); } /** @@ -40,7 +35,7 @@ protected function connect() { */ public function listShares() { $this->connect(); - $shares = array(); + $shares = []; $dh = $this->state->opendir('smb://' . $this->getHost()); while ($share = $this->state->readdir($dh)) { if ($share['type'] === 'file share') { @@ -62,10 +57,10 @@ public function getShare($name) { /** * Check if the smbclient php extension is available * - * @param System $system + * @param ISystem $system * @return bool */ - public static function available(System $system) { - return function_exists('smbclient_state_new'); + public static function available(ISystem $system) { + return $system->libSmbclientAvailable(); } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php index 130a5a070ff3..e829be28bf06 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeShare.php @@ -53,7 +53,7 @@ protected function getState() { } $this->state = new NativeState(); - $this->state->init($this->server->getAuth()); + $this->state->init($this->server->getAuth(), $this->server->getOptions()); return $this->state; } @@ -87,13 +87,14 @@ private function buildUrl($path) { * @throws \Icewind\SMB\Exception\InvalidTypeException */ public function dir($path) { - $files = array(); + $files = []; $dh = $this->getState()->opendir($this->buildUrl($path)); while ($file = $this->getState()->readdir($dh)) { $name = $file['name']; if ($name !== '.' and $name !== '..') { - $files [] = new NativeFileInfo($this, $path . '/' . $name, $name); + $fullPath = $path . '/' . $name; + $files [] = new NativeFileInfo($this, $fullPath, $name); } } @@ -106,11 +107,29 @@ public function dir($path) { * @return \Icewind\SMB\IFileInfo */ public function stat($path) { - return new NativeFileInfo($this, $path, basename($path), $this->getStat($path)); + $info = new NativeFileInfo($this, $path, self::mb_basename($path)); + + // trigger attribute loading + $info->getSize(); + + return $info; } - public function getStat($path) { - return $this->getState()->stat($this->buildUrl($path)); + /** + * Multibyte unicode safe version of basename() + * + * @param string $path + * @link http://php.net/manual/en/function.basename.php#121405 + * @return string + */ + protected static function mb_basename($path) { + if (preg_match('@^.*[\\\\/]([^\\\\/]+)$@s', $path, $matches)) { + return $matches[1]; + } elseif (preg_match('@^([^\\\\/]+)$@s', $path, $matches)) { + return $matches[1]; + } + + return ''; } /** @@ -178,12 +197,14 @@ public function rename($from, $to) { */ public function put($source, $target) { $sourceHandle = fopen($source, 'rb'); - $targetHandle = $this->getState()->create($this->buildUrl($target)); + $targetUrl = $this->buildUrl($target); + + $targetHandle = $this->getState()->create($targetUrl); while ($data = fread($sourceHandle, NativeReadStream::CHUNK_SIZE)) { - $this->getState()->write($targetHandle, $data); + $this->getState()->write($targetHandle, $data, $targetUrl); } - $this->getState()->close($targetHandle); + $this->getState()->close($targetHandle, $targetUrl); return true; } @@ -203,6 +224,12 @@ public function get($source, $target) { if (!$target) { throw new InvalidPathException('Invalid target path: Filename cannot be empty'); } + + $sourceHandle = $this->getState()->open($this->buildUrl($source), 'r'); + if (!$sourceHandle) { + throw new InvalidResourceException('Failed opening remote file "' . $source . '" for reading'); + } + $targetHandle = @fopen($target, 'wb'); if (!$targetHandle) { $error = error_get_last(); @@ -211,24 +238,19 @@ public function get($source, $target) { } else { $reason = 'Unknown error'; } + $this->getState()->close($sourceHandle, $this->buildUrl($source)); throw new InvalidResourceException('Failed opening local file "' . $target . '" for writing: ' . $reason); } - $sourceHandle = $this->getState()->open($this->buildUrl($source), 'r'); - if (!$sourceHandle) { - fclose($targetHandle); - throw new InvalidResourceException('Failed opening remote file "' . $source . '" for reading'); - } - while ($data = $this->getState()->read($sourceHandle, NativeReadStream::CHUNK_SIZE)) { fwrite($targetHandle, $data); } - $this->getState()->close($sourceHandle); + $this->getState()->close($sourceHandle, $this->buildUrl($source)); return true; } /** - * Open a readable stream top a remote file + * Open a readable stream to a remote file * * @param string $source * @return resource a read only stream with the contents of the remote file @@ -243,10 +265,11 @@ public function read($source) { } /** - * Open a readable stream top a remote file + * Open a writeable stream to a remote file + * Note: This method will truncate the file to 0bytes first * * @param string $source - * @return resource a read only stream with the contents of the remote file + * @return resource a writeable stream * * @throws \Icewind\SMB\Exception\NotFoundException * @throws \Icewind\SMB\Exception\InvalidTypeException @@ -257,6 +280,21 @@ public function write($source) { return NativeWriteStream::wrap($this->getState(), $handle, 'w', $url); } + /** + * Open a writeable stream and set the cursor to the end of the stream + * + * @param string $source + * @return resource a writeable stream + * + * @throws \Icewind\SMB\Exception\NotFoundException + * @throws \Icewind\SMB\Exception\InvalidTypeException + */ + public function append($source) { + $url = $this->buildUrl($source); + $handle = $this->getState()->open($url, "a+"); + return NativeWriteStream::wrap($this->getState(), $handle, "a", $url); + } + /** * Get extended attributes for the path * @@ -269,15 +307,14 @@ public function getAttribute($path, $attribute) { } /** - * Get extended attributes for the path + * Set extended attributes for the given path * * @param string $path * @param string $attribute attribute to get the info - * @param mixed $value - * @return string the attribute value + * @param string|int $value + * @return mixed the attribute value */ public function setAttribute($path, $attribute, $value) { - if ($attribute === 'system.dos_attr.mode' and is_int($value)) { $value = '0x' . dechex($value); } @@ -286,6 +323,8 @@ public function setAttribute($path, $attribute, $value) { } /** + * Set DOS comaptible node mode + * * @param string $path * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL * @return mixed @@ -295,16 +334,19 @@ public function setMode($path, $mode) { } /** + * Start smb notify listener + * Note: This is a blocking call + * * @param string $path * @return INotifyHandler */ public function notify($path) { - // php-smbclient does support notify (https://github.com/eduardok/libsmbclient-php/issues/29) + // php-smbclient does not 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()); + $share = new Share($this->server, $this->getName(), $this->server->getSystem()); return $share->notify($path); } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php index 179ba95beac8..3bfb1c3da243 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeState.php @@ -9,18 +9,21 @@ use Icewind\SMB\Exception\AlreadyExistsException; use Icewind\SMB\Exception\ConnectionRefusedException; +use Icewind\SMB\Exception\ConnectionResetException; use Icewind\SMB\Exception\Exception; use Icewind\SMB\Exception\FileInUseException; use Icewind\SMB\Exception\ForbiddenException; use Icewind\SMB\Exception\HostDownException; use Icewind\SMB\Exception\InvalidArgumentException; use Icewind\SMB\Exception\InvalidTypeException; +use Icewind\SMB\Exception\ConnectionAbortedException; use Icewind\SMB\Exception\NoRouteToHostException; use Icewind\SMB\Exception\NotEmptyException; use Icewind\SMB\Exception\NotFoundException; use Icewind\SMB\Exception\OutOfSpaceException; use Icewind\SMB\Exception\TimedOutException; use Icewind\SMB\IAuth; +use Icewind\SMB\IOptions; /** * Low level wrapper for libsmbclient-php with error handling @@ -47,6 +50,8 @@ class NativeState { 22 => InvalidArgumentException::class, 28 => OutOfSpaceException::class, 39 => NotEmptyException::class, + 103 => ConnectionAbortedException::class, + 104 => ConnectionResetException::class, 110 => TimedOutException::class, 111 => ConnectionRefusedException::class, 112 => HostDownException::class, @@ -76,14 +81,16 @@ protected function testResult($result, $uri) { /** * @param IAuth $auth + * @param IOptions $options * @return bool */ - public function init(IAuth $auth) { + public function init(IAuth $auth, IOptions $options) { if ($this->connected) { return true; } $this->state = smbclient_state_new(); smbclient_option_set($this->state, SMBCLIENT_OPT_AUTO_ANONYMOUS_LOGIN, false); + smbclient_option_set($this->state, SMBCLIENT_OPT_TIMEOUT, $options->getTimeout() * 1000); $auth->setExtraSmbClientOptions($this->state); $result = @smbclient_state_init($this->state, $auth->getWorkgroup(), $auth->getUsername(), $auth->getPassword()); @@ -233,13 +240,14 @@ public function read($file, $bytes) { /** * @param resource $file * @param string $data + * @param string $path * @param int $length * @return int */ - public function write($file, $data, $length = null) { + public function write($file, $data, $path, $length = null) { $result = @smbclient_write($this->state, $file, $data, $length); - $this->testResult($result, $file); + $this->testResult($result, $path); return $result; } @@ -268,10 +276,10 @@ public function ftruncate($file, $size) { return $result; } - public function close($file) { + public function close($file, $path) { $result = @smbclient_close($this->state, $file); - $this->testResult($result, $file); + $this->testResult($result, $path); return $result; } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php index 3b3c65de276e..c75afaa5f1d7 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeStream.php @@ -48,20 +48,24 @@ class NativeStream implements File { */ public static function wrap($state, $smbStream, $mode, $url) { stream_wrapper_register('nativesmb', NativeStream::class); - $context = stream_context_create(array( - 'nativesmb' => array( + $context = stream_context_create([ + 'nativesmb' => [ 'state' => $state, 'handle' => $smbStream, 'url' => $url - ) - )); + ] + ]); $fh = fopen('nativesmb://', $mode, false, $context); stream_wrapper_unregister('nativesmb'); return $fh; } public function stream_close() { - return $this->state->close($this->handle); + try { + return $this->state->close($this->handle, $this->url); + } catch (\Exception $e) { + return false; + } } public function stream_eof() { @@ -110,7 +114,7 @@ public function stream_tell() { } public function stream_write($data) { - return $this->state->write($this->handle, $data); + return $this->state->write($this->handle, $data, $this->url); } public function stream_truncate($size) { diff --git a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php index f5143a09ae28..4e90e5a655d2 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Native/NativeWriteStream.php @@ -25,7 +25,6 @@ public function stream_open($path, $mode, $options, &$opened_path) { $this->writeBuffer = fopen('php://memory', 'r+'); return parent::stream_open($path, $mode, $options, $opened_path); - } /** @@ -39,13 +38,13 @@ public function stream_open($path, $mode, $options, &$opened_path) { */ public static function wrap($state, $smbStream, $mode, $url) { stream_wrapper_register('nativesmb', NativeWriteStream::class); - $context = stream_context_create(array( - 'nativesmb' => array( + $context = stream_context_create([ + 'nativesmb' => [ 'state' => $state, 'handle' => $smbStream, 'url' => $url - ) - )); + ] + ]); $fh = fopen('nativesmb://', $mode, false, $context); stream_wrapper_unregister('nativesmb'); return $fh; @@ -62,7 +61,7 @@ public function stream_seek($offset, $whence = SEEK_SET) { private function flushWrite() { rewind($this->writeBuffer); - $this->state->write($this->handle, stream_get_contents($this->writeBuffer)); + $this->state->write($this->handle, stream_get_contents($this->writeBuffer), $this->url); $this->writeBuffer = fopen('php://memory', 'r+'); $this->bufferSize = 0; } @@ -80,8 +79,13 @@ public function stream_write($data) { } public function stream_close() { - $this->flushWrite(); - return parent::stream_close(); + try { + $this->flushWrite(); + $flushResult = true; + } catch (\Exception $e) { + $flushResult = false; + } + return parent::stream_close() && $flushResult; } public function stream_tell() { diff --git a/apps/files_external/3rdparty/icewind/smb/src/Options.php b/apps/files_external/3rdparty/icewind/smb/src/Options.php new file mode 100644 index 000000000000..7a0d0149b73e --- /dev/null +++ b/apps/files_external/3rdparty/icewind/smb/src/Options.php @@ -0,0 +1,35 @@ + + * + * @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 . + * + */ + +namespace Icewind\SMB; + +class Options implements IOptions { + /** @var int */ + private $timeout = 20; + + public function getTimeout() { + return $this->timeout; + } + + public function setTimeout($timeout) { + $this->timeout = $timeout; + } +} diff --git a/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php b/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php index b54168a520cb..807b0b872cff 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php +++ b/apps/files_external/3rdparty/icewind/smb/src/ServerFactory.php @@ -21,7 +21,6 @@ namespace Icewind\SMB; - use Icewind\SMB\Exception\DependencyException; use Icewind\SMB\Native\NativeServer; use Icewind\SMB\Wrapped\Server; @@ -32,8 +31,41 @@ class ServerFactory { Server::class ]; - /** @var System|null */ - private $system = null; + /** @var System */ + private $system; + + /** @var IOptions */ + private $options; + + /** @var ITimeZoneProvider */ + private $timeZoneProvider; + + /** + * ServerFactory constructor. + * + * @param IOptions|null $options + * @param ISystem|null $system + * @param ITimeZoneProvider|null $timeZoneProvider + */ + public function __construct( + IOptions $options = null, + ISystem $system = null, + ITimeZoneProvider $timeZoneProvider = null + ) { + if (is_null($options)) { + $options = new Options(); + } + if (is_null($system)) { + $system = new System(); + } + if (is_null($timeZoneProvider)) { + $timeZoneProvider = new TimeZoneProvider($system); + } + $this->options = $options; + $this->system = $system; + $this->timeZoneProvider = $timeZoneProvider; + } + /** * @param $host @@ -43,22 +75,11 @@ class ServerFactory { */ 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())); + if (call_user_func("$backend::available", $this->system)) { + return new $backend($host, $credentials, $this->system, $this->timeZoneProvider, $this->options); } } 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; - } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/System.php b/apps/files_external/3rdparty/icewind/smb/src/System.php index 30592dd26274..0e41ee032d6c 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/System.php +++ b/apps/files_external/3rdparty/icewind/smb/src/System.php @@ -9,14 +9,18 @@ use Icewind\SMB\Exception\Exception; -class System { - private $smbclient; +class System implements ISystem { + /** @var (string|bool)[] */ + private $paths = []; - private $net; - - private $stdbuf; - - public static function getFD($num) { + /** + * Get the path to a file descriptor of the current process + * + * @param int $num the file descriptor id + * @return string + * @throws Exception + */ + public function getFD($num) { $folders = [ '/proc/self/fd', '/dev/fd' @@ -30,26 +34,36 @@ public static function getFD($num) { } public function getSmbclientPath() { - if (!$this->smbclient) { - $this->smbclient = trim(`which smbclient`); - } - return $this->smbclient; + return $this->getBinaryPath('smbclient'); } public function getNetPath() { - if (!$this->net) { - $this->net = trim(`which net`); - } - return $this->net; + return $this->getBinaryPath('net'); + } + + public function getSmbcAclsPath() { + return $this->getBinaryPath('smbcacls'); + } + + public function getStdBufPath() { + return $this->getBinaryPath('stdbuf'); + } + + public function getDatePath() { + return $this->getBinaryPath('date'); + } + + public function libSmbclientAvailable() { + return function_exists('smbclient_state_new'); } - public function hasStdBuf() { - if (!$this->stdbuf) { + protected function getBinaryPath($binary) { + if (!isset($this->paths[$binary])) { $result = null; - $output = array(); - exec('which stdbuf 2>&1', $output, $result); - $this->stdbuf = $result === 0; + $output = []; + exec("which $binary 2>&1", $output, $result); + $this->paths[$binary] = $result === 0 ? trim(implode('', $output)) : false; } - return $this->stdbuf; + return $this->paths[$binary]; } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php b/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php index fcdf7e3e879b..7ae049c406f6 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php +++ b/apps/files_external/3rdparty/icewind/smb/src/TimeZoneProvider.php @@ -7,44 +7,48 @@ namespace Icewind\SMB; -class TimeZoneProvider { +class TimeZoneProvider implements ITimeZoneProvider { /** - * @var string + * @var string[] */ - private $host; + private $timeZones = []; /** - * @var string - */ - private $timeZone; - - /** - * @var System + * @var ISystem */ private $system; /** - * @param string $host - * @param System $system + * @param ISystem $system */ - public function __construct($host, System $system) { - $this->host = $host; + public function __construct(ISystem $system) { $this->system = $system; } - public function get() { - if (!$this->timeZone) { + public function get($host) { + if (!isset($this->timeZones[$host])) { + $timeZone = null; $net = $this->system->getNetPath(); - if ($net) { - $command = sprintf('%s time zone -S %s', + // for local domain names we can assume same timezone + if ($net && $host && strpos($host, '.') !== false) { + $command = sprintf( + '%s time zone -S %s', $net, - escapeshellarg($this->host) + escapeshellarg($host) ); - $this->timeZone = exec($command); - } else { // fallback to server timezone - $this->timeZone = date_default_timezone_get(); + $timeZone = exec($command); + } + + if (!$timeZone) { + $date = $this->system->getDatePath(); + if ($date) { + $timeZone = exec($date . " +%z"); + } else { + $timeZone = date_default_timezone_get(); + } } + $this->timeZones[$host] = $timeZone; } - return $this->timeZone; + return $this->timeZones[$host]; } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php index 7eddb85ac4f9..347b63db1102 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Connection.php @@ -20,7 +20,7 @@ class Connection extends RawConnection { /** @var Parser */ private $parser; - public function __construct($command, Parser $parser, $env = array()) { + public function __construct($command, Parser $parser, $env = []) { parent::__construct($command, $env); $this->parser = $parser; } @@ -65,8 +65,12 @@ public function read(callable $callback = null) { $promptLine = $this->readLine(); //first line is prompt $this->parser->checkConnectionError($promptLine); - $output = array(); - $line = $this->readLine(); + $output = []; + if (!$this->isPrompt($promptLine)) { + $line = $promptLine; + } else { + $line = $this->readLine(); + } if ($line === false) { $this->unknownError($promptLine); } @@ -113,8 +117,9 @@ private function unknownError($promptLine = '') { } public function close($terminate = true) { - if (is_resource($this->getInputStream())) { - $this->write('close' . PHP_EOL); + if (get_resource_type($this->getInputStream()) === 'stream') { + // ignore any errors while trying to send the close command, the process might already be dead + @$this->write('close' . PHP_EOL); } parent::close($terminate); } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php index 094e665a9356..a310a6bc9132 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/FileInfo.php @@ -7,6 +7,7 @@ namespace Icewind\SMB\Wrapped; +use Icewind\SMB\ACL; use Icewind\SMB\IFileInfo; class FileInfo implements IFileInfo { @@ -35,19 +36,26 @@ class FileInfo implements IFileInfo { */ protected $mode; + /** + * @var callable + */ + protected $aclCallback; + /** * @param string $path * @param string $name * @param int $size * @param int $time * @param int $mode + * @param callable $aclCallback */ - public function __construct($path, $name, $size, $time, $mode) { + public function __construct($path, $name, $size, $time, $mode, callable $aclCallback) { $this->path = $path; $this->name = $name; $this->size = $size; $this->time = $time; $this->mode = $mode; + $this->aclCallback = $aclCallback; } /** @@ -112,4 +120,11 @@ public function isSystem() { public function isArchived() { return (bool)($this->mode & IFileInfo::MODE_ARCHIVE); } + + /** + * @return ACL[] + */ + public function getAcls(): array { + return ($this->aclCallback)(); + } } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php index a32ae3cafa44..090734381bbd 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/NotifyHandler.php @@ -8,7 +8,6 @@ namespace Icewind\SMB\Wrapped; - use Icewind\SMB\Change; use Icewind\SMB\Exception\Exception; use Icewind\SMB\Exception\RevisionMismatchException; diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php index c446ae85b305..a28432e43194 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Parser.php @@ -19,17 +19,20 @@ 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 '; /** - * @var \Icewind\SMB\TimeZoneProvider + * @var string */ - protected $timeZoneProvider; + protected $timeZone; + + /** + * @var string + */ + private $host; - // todo replace with static once <5.6 support is dropped // see error.h const EXCEPTION_MAP = [ ErrorCodes::LogonFailure => AuthenticationException::class, @@ -55,10 +58,10 @@ class Parser { ]; /** - * @param TimeZoneProvider $timeZoneProvider + * @param string $timeZone */ - public function __construct(TimeZoneProvider $timeZoneProvider) { - $this->timeZoneProvider = $timeZoneProvider; + public function __construct($timeZone) { + $this->timeZone = $timeZone; } private function getErrorCode($line) { @@ -135,28 +138,34 @@ public function parseStat($output) { $name = isset($words[0]) ? $words[0] : ''; $value = isset($words[1]) ? $words[1] : ''; $value = trim($value); - $data[$name] = $value; + + if (!isset($data[$name])) { + $data[$name] = $value; + } } return [ 'mtime' => strtotime($data['write_time']), - 'mode' => hexdec(substr($data['attributes'], strpos($data['attributes'], '('), -1)), + 'mode' => hexdec(substr($data['attributes'], strpos($data['attributes'], '(') + 1, -1)), 'size' => isset($data['stream']) ? (int)(explode(' ', $data['stream'])[1]) : 0 ]; } - public function parseDir($output, $basePath) { + public function parseDir($output, $basePath, callable $aclCallback) { //last line is used space array_pop($output); $regex = '/^\s*(.*?)\s\s\s\s+(?:([NDHARS]*)\s+)?([0-9]+)\s+(.*)$/'; //2 spaces, filename, optional type, size, date - $content = array(); + $content = []; foreach ($output as $line) { if (preg_match($regex, $line, $matches)) { list(, $name, $mode, $size, $time) = $matches; if ($name !== '.' and $name !== '..') { $mode = $this->parseMode($mode); - $time = strtotime($time . ' ' . $this->timeZoneProvider->get()); - $content[] = new FileInfo($basePath . '/' . $name, $name, $size, $time, $mode); + $time = strtotime($time . ' ' . $this->timeZone); + $path = $basePath . '/' . $name; + $content[] = new FileInfo($path, $name, $size, $time, $mode, function () use ($aclCallback, $path) { + return $aclCallback($path); + }); } } } @@ -164,14 +173,14 @@ public function parseDir($output, $basePath) { } public function parseListShares($output) { - $shareNames = array(); + $shareNames = []; foreach ($output as $line) { if (strpos($line, '|')) { list($type, $name, $description) = explode('|', $line); if (strtolower($type) === 'disk') { $shareNames[$name] = $description; } - } else if (strpos($line, 'Disk')) { + } elseif (strpos($line, 'Disk')) { // new output format list($name, $description) = explode('Disk', $line); $shareNames[trim($name)] = trim($description); diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php index f29cf60eb664..3a114af5e4f1 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/RawConnection.php @@ -173,18 +173,6 @@ public function close($terminate = true) { return; } if ($terminate) { - // if for case that posix_ functions are not available - if (function_exists('posix_kill')) { - $status = proc_get_status($this->process); - $ppid = $status['pid']; - $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`); - foreach ($pids as $pid) { - if (is_numeric($pid)) { - //9 is the SIGKILL signal - posix_kill($pid, 9); - } - } - } proc_terminate($this->process); } proc_close($this->process); diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php index cc0f13f36064..b3763a732457 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Server.php @@ -13,22 +13,22 @@ use Icewind\SMB\Exception\ConnectionException; use Icewind\SMB\Exception\InvalidHostException; use Icewind\SMB\IShare; -use Icewind\SMB\System; +use Icewind\SMB\ISystem; class Server extends AbstractServer { /** * Check if the smbclient php extension is available * - * @param System $system + * @param ISystem $system * @return bool */ - public static function available(System $system) { + public static function available(ISystem $system) { return $system->getSmbclientPath(); } private function getAuthFileArgument() { if ($this->getAuth()->getUsername()) { - return '--authentication-file=' . System::getFD(3); + return '--authentication-file=' . $this->system->getFD(3); } else { return ''; } @@ -42,7 +42,8 @@ private function getAuthFileArgument() { * @throws ConnectException */ public function listShares() { - $command = sprintf('%s %s %s -L %s', + $command = sprintf( + '%s %s %s -L %s', $this->system->getSmbclientPath(), $this->getAuthFileArgument(), $this->getAuth()->getExtraCommandLineArguments(), @@ -73,7 +74,7 @@ public function listShares() { $shareNames = $parser->parseListShares($output); - $shares = array(); + $shares = []; foreach ($shareNames as $name => $description) { $shares[] = $this->getShare($name); } diff --git a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php index ca88af219a88..e0df1f603266 100644 --- a/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php +++ b/apps/files_external/3rdparty/icewind/smb/src/Wrapped/Share.php @@ -8,16 +8,20 @@ namespace Icewind\SMB\Wrapped; use Icewind\SMB\AbstractShare; +use Icewind\SMB\ACL; 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\Exception\InvalidRequestException; +use Icewind\SMB\IFileInfo; use Icewind\SMB\INotifyHandler; use Icewind\SMB\IServer; -use Icewind\SMB\System; -use Icewind\SMB\TimeZoneProvider; +use Icewind\SMB\ISystem; use Icewind\Streams\CallbackWrapper; +use Icewind\SMB\Native\NativeShare; +use Icewind\SMB\Native\NativeServer; class Share extends AbstractShare { /** @@ -41,7 +45,7 @@ class Share extends AbstractShare { protected $parser; /** - * @var System + * @var ISystem */ private $system; @@ -52,31 +56,36 @@ class Share extends AbstractShare { FileInfo::MODE_SYSTEM => 's' ]; + const EXEC_CMD = 'exec'; + /** * @param IServer $server * @param string $name - * @param System $system + * @param ISystem $system */ - public function __construct(IServer $server, $name, System $system = null) { + public function __construct(IServer $server, $name, ISystem $system) { parent::__construct(); $this->server = $server; $this->name = $name; - $this->system = (!is_null($system)) ? $system : new System(); - $this->parser = new Parser(new TimeZoneProvider($this->server->getHost(), $this->system)); + $this->system = $system; + $this->parser = new Parser($server->getTimeZone()); } private function getAuthFileArgument() { if ($this->server->getAuth()->getUsername()) { - return '--authentication-file=' . System::getFD(3); + return '--authentication-file=' . $this->system->getFD(3); } else { return ''; } } protected function getConnection() { - $command = sprintf('%s%s %s %s %s', - $this->system->hasStdBuf() ? 'stdbuf -o0 ' : '', + $command = sprintf( + '%s %s%s -t %s %s %s %s', + self::EXEC_CMD, + $this->system->getStdBufPath() ? $this->system->getStdBufPath() . ' -o0 ' : '', $this->system->getSmbclientPath(), + $this->server->getOptions()->getTimeout(), $this->getAuthFileArgument(), $this->server->getAuth()->getExtraCommandLineArguments(), escapeshellarg('//' . $this->server->getHost() . '/' . $this->name) @@ -145,7 +154,9 @@ public function dir($path) { $this->execute('cd /'); - return $this->parser->parseDir($output, $path); + return $this->parser->parseDir($output, $path, function ($path) { + return $this->getAcls($path); + }); } /** @@ -153,6 +164,19 @@ public function dir($path) { * @return \Icewind\SMB\IFileInfo */ public function stat($path) { + // some windows server setups don't seem to like the allinfo command + // use the dir command instead to get the file info where possible + if ($path !== "" && $path !== "/") { + $parent = dirname($path); + $dir = $this->dir($parent); + $file = array_values(array_filter($dir, function (IFileInfo $info) use ($path) { + return $info->getPath() === $path; + })); + if ($file) { + return $file[0]; + } + } + $escapedPath = $this->escapePath($path); $output = $this->execute('allinfo ' . $escapedPath); // Windows and non Windows Fileserver may respond different @@ -165,7 +189,9 @@ public function stat($path) { $this->parseOutput($output, $path); } $stat = $this->parser->parseStat($output); - return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode']); + return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode'], function () use ($path) { + return $this->getAcls($path); + }); } /** @@ -294,7 +320,7 @@ public function read($source) { // since we can't re-use the same file descriptor over multiple calls $connection = $this->getConnection(); - $connection->write('get ' . $source . ' ' . System::getFD(5)); + $connection->write('get ' . $source . ' ' . $this->system->getFD(5)); $connection->write('exit'); $fh = $connection->getFileOutputStream(); stream_context_set_option($fh, 'file', 'connection', $connection); @@ -317,7 +343,7 @@ public function write($target) { $connection = $this->getConnection(); $fh = $connection->getFileInputStream(); - $connection->write('put ' . System::getFD(4) . ' ' . $target); + $connection->write('put ' . $this->system->getFD(4) . ' ' . $target); $connection->write('exit'); // use a close callback to ensure the upload is finished before continuing @@ -327,6 +353,18 @@ public function write($target) { }); } + /** + * Append to stream + * Note: smbclient does not support this (Use php-libsmbclient) + * + * @param string $target + * + * @throws \Icewind\SMB\Exception\DependencyException + */ + public function append($target) { + throw new DependencyException('php-libsmbclient is required for append'); + } + /** * @param string $path * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL @@ -363,7 +401,7 @@ public function setMode($path, $mode) { * @throws DependencyException */ public function notify($path) { - if (!$this->system->hasStdBuf()) { //stdbuf is required to disable smbclient's output buffering + if (!$this->system->getStdBufPath()) { //stdbuf is required to disable smbclient's output buffering throw new DependencyException('stdbuf is required for usage of the notify command'); } $connection = $this->getConnection(); // use a fresh connection since the notify command blocks the process @@ -388,13 +426,13 @@ protected function execute($command) { * @param string[] $lines * @param string $path * - * @throws NotFoundException + * @return bool * @throws \Icewind\SMB\Exception\AlreadyExistsException * @throws \Icewind\SMB\Exception\AccessDeniedException * @throws \Icewind\SMB\Exception\NotEmptyException * @throws \Icewind\SMB\Exception\InvalidTypeException * @throws \Icewind\SMB\Exception\Exception - * @return bool + * @throws NotFoundException */ protected function parseOutput($lines, $path = '') { if (count($lines) === 0) { @@ -437,6 +475,83 @@ protected function escapeLocalPath($path) { return '"' . $path . '"'; } + protected function getAcls($path) { + $commandPath = $this->system->getSmbcAclsPath(); + if (!$commandPath) { + return []; + } + + $command = sprintf( + '%s %s %s %s/%s %s', + $commandPath, + $this->getAuthFileArgument(), + $this->server->getAuth()->getExtraCommandLineArguments(), + escapeshellarg('//' . $this->server->getHost()), + escapeshellarg($this->name), + escapeshellarg($path) + ); + $connection = new RawConnection($command); + $connection->writeAuthentication($this->server->getAuth()->getUsername(), $this->server->getAuth()->getPassword()); + $connection->connect(); + if (!$connection->isValid()) { + throw new ConnectionException($connection->readLine()); + } + + $rawAcls = $connection->readAll(); + + $acls = []; + foreach ($rawAcls as $acl) { + [$type, $acl] = explode(':', $acl, 2); + if ($type !== 'ACL') { + continue; + } + [$user, $permissions] = explode(':', $acl, 2); + [$type, $flags, $mask] = explode('/', $permissions); + + $type = $type === 'ALLOWED' ? ACL::TYPE_ALLOW : ACL::TYPE_DENY; + + $flagsInt = 0; + foreach (explode('|', $flags) as $flagString) { + if ($flagString === 'OI') { + $flagsInt += ACL::FLAG_OBJECT_INHERIT; + } elseif ($flagString === 'CI') { + $flagsInt += ACL::FLAG_CONTAINER_INHERIT; + } + } + + if (substr($mask, 0, 2) === '0x') { + $maskInt = hexdec($mask); + } else { + $maskInt = 0; + foreach (explode('|', $mask) as $maskString) { + if ($maskString === 'R') { + $maskInt += ACL::MASK_READ; + } elseif ($maskString === 'W') { + $maskInt += ACL::MASK_WRITE; + } elseif ($maskString === 'X') { + $maskInt += ACL::MASK_EXECUTE; + } elseif ($maskString === 'D') { + $maskInt += ACL::MASK_DELETE; + } elseif ($maskString === 'READ') { + $maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE; + } elseif ($maskString === 'CHANGE') { + $maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE + ACL::MASK_WRITE + ACL::MASK_DELETE; + } elseif ($maskString === 'FULL') { + $maskInt += ACL::MASK_READ + ACL::MASK_EXECUTE + ACL::MASK_WRITE + ACL::MASK_DELETE; + } + } + } + + if (isset($acls[$user])) { + $existing = $acls[$user]; + $maskInt += $existing->getMask(); + } + $acls[$user] = new ACL($type, $flagsInt, $maskInt); + } + + return $acls; + } + public function __destruct() { unset($this->connection); } diff --git a/apps/files_external/3rdparty/icewind/streams/.gitignore b/apps/files_external/3rdparty/icewind/streams/.gitignore index 4f389129e2d9..e2a9a5109fa0 100644 --- a/apps/files_external/3rdparty/icewind/streams/.gitignore +++ b/apps/files_external/3rdparty/icewind/streams/.gitignore @@ -1,3 +1,5 @@ .idea vendor composer.lock +build +example.php diff --git a/apps/files_external/3rdparty/icewind/streams/.scrutinizer.yml b/apps/files_external/3rdparty/icewind/streams/.scrutinizer.yml new file mode 100644 index 000000000000..0c7c78622a5f --- /dev/null +++ b/apps/files_external/3rdparty/icewind/streams/.scrutinizer.yml @@ -0,0 +1,13 @@ +build: + nodes: + analysis: + tests: + override: + - php-scrutinizer-run +tools: + php_sim: true + php_pdepend: true + php_analyzer: true +filter: + excluded_paths: + - 'tests/*' diff --git a/apps/files_external/3rdparty/icewind/streams/.travis.yml b/apps/files_external/3rdparty/icewind/streams/.travis.yml index d2e1afaad675..870956fc6711 100644 --- a/apps/files_external/3rdparty/icewind/streams/.travis.yml +++ b/apps/files_external/3rdparty/icewind/streams/.travis.yml @@ -1,27 +1,18 @@ language: php php: - - 5.4 - - 5.5 - 5.6 - 7.0 - - hhvm - -matrix: - allow_failures: - - php: hhvm # due to facebook/hhvm#3321 - -env: - global: - - CURRENT_DIR=`pwd` + - 7.1 + - 7.2 + - 7.3 + - 7.4 install: - composer install --dev --no-interaction script: - mkdir -p build/logs - - cd tests - - phpunit --coverage-clover ../build/logs/clover.xml --configuration phpunit.xml + - vendor/bin/phpunit --coverage-clover build/logs/clover.xml --configuration tests/phpunit.xml after_script: - - cd $CURRENT_DIR - - php vendor/bin/coveralls -v + - vendor/bin/php-coveralls -v diff --git a/apps/files_external/3rdparty/icewind/streams/README.md b/apps/files_external/3rdparty/icewind/streams/README.md index ca13db28e441..e3b4bbfedf14 100644 --- a/apps/files_external/3rdparty/icewind/streams/README.md +++ b/apps/files_external/3rdparty/icewind/streams/README.md @@ -1,4 +1,4 @@ -#Streams# +# Streams # [![Build Status](https://travis-ci.org/icewind1991/Streams.svg?branch=master)](https://travis-ci.org/icewind1991/Streams) [![Coverage Status](https://img.shields.io/coveralls/icewind1991/Streams.svg)](https://coveralls.io/r/icewind1991/Streams?branch=master) @@ -6,7 +6,7 @@ Generic stream wrappers for php. -##CallBackWrapper## +## CallBackWrapper ## A `CallBackWrapper` can be used to register callbacks on read, write and closing of the stream, it wraps an existing stream and can thus be used for any stream in php @@ -14,7 +14,7 @@ it wraps an existing stream and can thus be used for any stream in php The callbacks are passed in the stream context along with the source stream and can be any valid [php callable](http://php.net/manual/en/language.types.callable.php) -###Example### +### Example ### ```php =5.3" + "require": { + "php": ">=5.6" }, - "require-dev" : { - "satooshi/php-coveralls": "v1.0.0", - "phpunit/phpunit": "^4.8" + "require-dev": { + "php-coveralls/php-coveralls": "v2.1.0", + "phpunit/phpunit": "^5.7" }, - "autoload" : { + "autoload": { "psr-4": { - "Icewind\\Streams\\Tests\\": "tests/", "Icewind\\Streams\\": "src/" } + }, + "autoload-dev": { + "psr-4": { + "Icewind\\Streams\\Tests\\": "tests/" + } } } diff --git a/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php index 4eef55681c7f..be62e3f66910 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php @@ -44,38 +44,43 @@ class CallbackWrapper extends Wrapper { */ protected $readDirCallBack; + /** + * @var callable + */ + protected $preCloseCallback; + /** * Wraps a stream with the provided callbacks * * @param resource $source - * @param callable $read (optional) - * @param callable $write (optional) - * @param callable $close (optional) - * @param callable $readDir (optional) - * @return resource + * @param callable|null $read (optional) + * @param callable|null $write (optional) + * @param callable|null $close (optional) + * @param callable|null $readDir (optional) + * @param callable|null $preClose (optional) + * @return resource|bool * - * @throws \BadMethodCallException */ - public static function wrap($source, $read = null, $write = null, $close = null, $readDir = null) { - $context = stream_context_create(array( - 'callback' => array( - 'source' => $source, - 'read' => $read, - 'write' => $write, - 'close' => $close, - 'readDir' => $readDir - ) - )); - return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\CallbackWrapper'); + public static function wrap($source, $read = null, $write = null, $close = null, $readDir = null, $preClose = null) { + $context = [ + 'source' => $source, + 'read' => $read, + 'write' => $write, + 'close' => $close, + 'readDir' => $readDir, + 'preClose' => $preClose, + ]; + return self::wrapSource($source, $context); } protected function open() { - $context = $this->loadContext('callback'); + $context = $this->loadContext(); $this->readCallback = $context['read']; $this->writeCallback = $context['write']; $this->closeCallback = $context['close']; $this->readDirCallBack = $context['readDir']; + $this->preCloseCallback = $context['preClose']; return true; } @@ -90,7 +95,7 @@ public function stream_open($path, $mode, $options, &$opened_path) { public function stream_read($count) { $result = parent::stream_read($count); if (is_callable($this->readCallback)) { - call_user_func($this->readCallback, $count); + call_user_func($this->readCallback, strlen($result)); } return $result; } @@ -104,6 +109,11 @@ public function stream_write($data) { } public function stream_close() { + if (is_callable($this->preCloseCallback)) { + call_user_func($this->preCloseCallback, $this->source); + // prevent further calls by potential PHP 7 GC ghosts + $this->preCloseCallback = null; + } $result = parent::stream_close(); if (is_callable($this->closeCallback)) { call_user_func($this->closeCallback); diff --git a/apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php new file mode 100644 index 000000000000..d02434012293 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/streams/src/CountWrapper.php @@ -0,0 +1,103 @@ + + * + * @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 . + * + */ + +namespace Icewind\Streams; + +/** + * Wrapper that counts the amount of data read and written + * + * The following options should be passed in the context when opening the stream + * [ + * 'callback' => [ + * 'source' => resource + * 'callback' => function($readCount, $writeCount){} + * ] + * ] + * + * The callback will be called when the stream is closed + */ +class CountWrapper extends Wrapper { + /** + * @var int + */ + protected $readCount = 0; + + /** + * @var int + */ + protected $writeCount = 0; + + /** + * @var callable + */ + protected $callback; + + /** + * Wraps a stream with the provided callbacks + * + * @param resource $source + * @param callable $callback + * @return resource|bool + * + * @throws \BadMethodCallException + */ + public static function wrap($source, $callback) { + if (!is_callable($callback)) { + throw new \InvalidArgumentException('Invalid or missing callback'); + } + return self::wrapSource($source, [ + 'source' => $source, + 'callback' => $callback + ]); + } + + protected function open() { + $context = $this->loadContext(); + $this->callback = $context['callback']; + return true; + } + + public function dir_opendir($path, $options) { + return $this->open(); + } + + public function stream_open($path, $mode, $options, &$opened_path) { + return $this->open(); + } + + public function stream_read($count) { + $result = parent::stream_read($count); + $this->readCount += strlen($result); + return $result; + } + + public function stream_write($data) { + $result = parent::stream_write($data); + $this->writeCount += strlen($data); + return $result; + } + + public function stream_close() { + $result = parent::stream_close(); + call_user_func($this->callback, $this->readCount, $this->writeCount); + return $result; + } +} diff --git a/apps/files_external/3rdparty/icewind/streams/src/Directory.php b/apps/files_external/3rdparty/icewind/streams/src/Directory.php index c80a878386b5..912be76acfab 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/Directory.php +++ b/apps/files_external/3rdparty/icewind/streams/src/Directory.php @@ -19,7 +19,7 @@ interface Directory { public function dir_opendir($path, $options); /** - * @return string + * @return string|bool */ public function dir_readdir(); diff --git a/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php b/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php index 4b8696990007..80b27e8bab85 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php +++ b/apps/files_external/3rdparty/icewind/streams/src/DirectoryFilter.php @@ -25,7 +25,7 @@ class DirectoryFilter extends DirectoryWrapper { * @return bool */ public function dir_opendir($path, $options) { - $context = $this->loadContext('filter'); + $context = $this->loadContext(); $this->filter = $context['filter']; return true; } @@ -36,7 +36,7 @@ public function dir_opendir($path, $options) { public function dir_readdir() { $file = readdir($this->source); $filter = $this->filter; - // keep reading untill we have an accepted entry or we're at the end of the folder + // keep reading until we have an accepted entry or we're at the end of the folder while ($file !== false && $filter($file) === false) { $file = readdir($this->source); } @@ -46,15 +46,12 @@ public function dir_readdir() { /** * @param resource $source * @param callable $filter - * @return resource + * @return resource|bool */ public static function wrap($source, callable $filter) { - $options = array( - 'filter' => array( - 'source' => $source, - 'filter' => $filter - ) - ); - return self::wrapWithOptions($options, '\Icewind\Streams\DirectoryFilter'); + return self::wrapSource($source, [ + 'source' => $source, + 'filter' => $filter + ]); } } diff --git a/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php index 63e4805a807c..7f2f5c291c6a 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/DirectoryWrapper.php @@ -7,37 +7,9 @@ namespace Icewind\Streams; -class DirectoryWrapper implements Directory { - /** - * @var resource - */ - public $context; - - /** - * @var resource - */ - protected $source; - - /** - * Load the source from the stream context and return the context options - * - * @param string $name - * @return array - * @throws \Exception - */ - protected function loadContext($name) { - $context = stream_context_get_options($this->context); - if (isset($context[$name])) { - $context = $context[$name]; - } else { - throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set'); - } - if (isset($context['source']) and is_resource($context['source'])) { - $this->source = $context['source']; - } else { - throw new \BadMethodCallException('Invalid context, source not set'); - } - return $context; +class DirectoryWrapper extends Wrapper implements Directory { + public function stream_open($path, $mode, $options, &$opened_path) { + return false; } /** @@ -46,7 +18,7 @@ protected function loadContext($name) { * @return bool */ public function dir_opendir($path, $options) { - $this->loadContext('dir'); + $this->loadContext(); return true; } @@ -72,17 +44,4 @@ public function dir_rewinddir() { rewinddir($this->source); return true; } - - /** - * @param array $options the options for the context to wrap the stream with - * @param string $class - * @return resource - */ - protected static function wrapWithOptions($options, $class) { - $context = stream_context_create($options); - stream_wrapper_register('dirwrapper', $class); - $wrapped = opendir('dirwrapper://', $context); - stream_wrapper_unregister('dirwrapper'); - return $wrapped; - } } diff --git a/apps/files_external/3rdparty/icewind/streams/src/HashWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/HashWrapper.php new file mode 100644 index 000000000000..0628d8bc72be --- /dev/null +++ b/apps/files_external/3rdparty/icewind/streams/src/HashWrapper.php @@ -0,0 +1,80 @@ + + * + * @author Roeland Jago Douma + * + * @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 . + * + */ + +namespace Icewind\Streams; + + +abstract class HashWrapper extends Wrapper { + + /** + * @var callable + */ + private $callback; + + /** + * @var resource + */ + private $hashContext; + + /** + * Wraps a stream to make it seekable + * + * @param resource $source + * @param string $hash + * @param callable $callback + * @return resource|bool + * + * @throws \BadMethodCallException + */ + public static function wrap($source, $hash, $callback) { + $context = [ + 'hash' => $hash, + 'callback' => $callback, + ]; + return self::wrapSource($source, $context); + } + + public function dir_opendir($path, $options) { + return false; + } + + public function stream_open($path, $mode, $options, &$opened_path) { + $context = $this->loadContext(); + $this->callback = $context['callback']; + $this->hashContext = hash_init($context['hash']); + return true; + } + + protected function updateHash($data) { + hash_update($this->hashContext, $data); + } + + public function stream_close() { + $hash = hash_final($this->hashContext); + if ($this->hashContext !== false && is_callable($this->callback)) { + call_user_func($this->callback, $hash); + } + return parent::stream_close(); + } + +} \ No newline at end of file diff --git a/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php index 6dfa42a8b684..057c1992f9c5 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php +++ b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php @@ -20,7 +20,7 @@ * * Either 'array' or 'iterator' need to be set, if both are set, 'iterator' takes preference */ -class IteratorDirectory implements Directory { +class IteratorDirectory extends WrapperHandler implements Directory { /** * @var resource */ @@ -36,15 +36,10 @@ class IteratorDirectory implements Directory { * * @param string $name * @return array - * @throws \Exception + * @throws \BadMethodCallException */ - protected function loadContext($name) { - $context = stream_context_get_options($this->context); - if (isset($context[$name])) { - $context = $context[$name]; - } else { - throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set'); - } + protected function loadContext($name = null) { + $context = parent::loadContext($name); if (isset($context['iterator'])) { $this->iterator = $context['iterator']; } else if (isset($context['array'])) { @@ -61,12 +56,12 @@ protected function loadContext($name) { * @return bool */ public function dir_opendir($path, $options) { - $this->loadContext('dir'); + $this->loadContext(); return true; } /** - * @return string + * @return string|bool */ public function dir_readdir() { if ($this->iterator->valid()) { @@ -97,27 +92,22 @@ public function dir_rewinddir() { * Creates a directory handle from the provided array or iterator * * @param \Iterator | array $source - * @return resource + * @return resource|bool * * @throws \BadMethodCallException */ public static function wrap($source) { if ($source instanceof \Iterator) { - $context = stream_context_create(array( - 'dir' => array( - 'iterator' => $source) - )); + $options = [ + 'iterator' => $source + ]; } else if (is_array($source)) { - $context = stream_context_create(array( - 'dir' => array( - 'array' => $source) - )); + $options = [ + 'array' => $source + ]; } else { throw new \BadMethodCallException('$source should be an Iterator or array'); } - stream_wrapper_register('iterator', '\Icewind\Streams\IteratorDirectory'); - $wrapped = opendir('iterator://', $context); - stream_wrapper_unregister('iterator'); - return $wrapped; + return self::wrapSource(self::NO_SOURCE_DIR, $options); } } diff --git a/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php index b6c71d98fc4a..92aef2c7a2d2 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php @@ -11,29 +11,17 @@ * Stream wrapper that does nothing, used for tests */ class NullWrapper extends Wrapper { - /** - * Wraps a stream with the provided callbacks - * - * @param resource $source - * @return resource - * - * @throws \BadMethodCallException - */ public static function wrap($source) { - $context = stream_context_create(array( - 'null' => array( - 'source' => $source) - )); - return Wrapper::wrapSource($source, $context, 'null', '\Icewind\Streams\NullWrapper'); + return self::wrapSource($source); } public function stream_open($path, $mode, $options, &$opened_path) { - $this->loadContext('null'); + $this->loadContext(); return true; } public function dir_opendir($path, $options) { - $this->loadContext('null'); + $this->loadContext(); return true; } } diff --git a/apps/files_external/3rdparty/icewind/streams/src/Path.php b/apps/files_external/3rdparty/icewind/streams/src/Path.php index bef9fd5f6162..42d74a2ac1a2 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/Path.php +++ b/apps/files_external/3rdparty/icewind/streams/src/Path.php @@ -38,7 +38,7 @@ class Path { * @param string $class * @param array $contextOptions */ - public function __construct($class, $contextOptions = array()) { + public function __construct($class, $contextOptions = []) { $this->class = $class; $this->contextOptions = $contextOptions; } @@ -75,7 +75,7 @@ protected function unregister() { */ protected function appendDefaultContent($values) { if (!is_array(current($values))) { - $values = array($this->getProtocol() => $values); + $values = [$this->getProtocol() => $values]; } $context = stream_context_get_default(); $defaults = stream_context_get_options($context); diff --git a/apps/files_external/3rdparty/icewind/streams/src/PathWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/PathWrapper.php index 88af7e17b336..d9f3014c3812 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/PathWrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/PathWrapper.php @@ -16,10 +16,8 @@ class PathWrapper extends NullWrapper { * @return Path|string */ public static function getPath($source) { - return new Path(__CLASS__, [ - 'null' => [ - 'source' => $source - ] + return new Path(NullWrapper::class, [ + NullWrapper::getProtocol() => ['source' => $source] ]); } } diff --git a/apps/files_external/3rdparty/icewind/streams/src/ReadHashWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/ReadHashWrapper.php new file mode 100644 index 000000000000..16cf006ccf51 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/streams/src/ReadHashWrapper.php @@ -0,0 +1,40 @@ + + * + * @author Roeland Jago Douma + * + * @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 . + * + */ + +namespace Icewind\Streams; + +/** + * Wrapper that calculates the hash on the stream on read + * + * The stream and hash should be passed in when wrapping the stream. + * On close the callback will be called with the calculated checksum. + * + * For supported hashes see: http://php.net/manual/en/function.hash-algos.php + */ +class ReadHashWrapper extends HashWrapper { + public function stream_read($count) { + $data = parent::stream_read($count); + $this->updateHash($data); + return $data; + } +} diff --git a/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php index 8238f19f7c93..d4727aa96cd4 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/RetryWrapper.php @@ -11,25 +11,8 @@ * Wrapper that retries reads/writes to remote streams that dont deliver/recieve all requested data at once */ class RetryWrapper extends Wrapper { - - /** - * Wraps a stream with the provided callbacks - * - * @param resource $source - * @return resource - */ public static function wrap($source) { - $context = stream_context_create(array( - 'retry' => array( - 'source' => $source - ) - )); - return Wrapper::wrapSource($source, $context, 'retry', '\Icewind\Streams\RetryWrapper'); - } - - protected function open() { - $this->loadContext('retry'); - return true; + return self::wrapSource($source); } public function dir_opendir($path, $options) { @@ -37,7 +20,8 @@ public function dir_opendir($path, $options) { } public function stream_open($path, $mode, $options, &$opened_path) { - return $this->open(); + $this->loadContext(); + return true; } public function stream_read($count) { diff --git a/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php index d41fd73ec9c2..f7abbc514251 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/SeekableWrapper.php @@ -25,21 +25,8 @@ class SeekableWrapper extends Wrapper { */ protected $cache; - /** - * Wraps a stream to make it seekable - * - * @param resource $source - * @return resource - * - * @throws \BadMethodCallException - */ public static function wrap($source) { - $context = stream_context_create(array( - 'callback' => array( - 'source' => $source - ) - )); - return Wrapper::wrapSource($source, $context, 'callback', '\Icewind\Streams\SeekableWrapper'); + return self::wrapSource($source); } public function dir_opendir($path, $options) { @@ -47,8 +34,12 @@ public function dir_opendir($path, $options) { } public function stream_open($path, $mode, $options, &$opened_path) { - $this->loadContext('callback'); - $this->cache = fopen('php://temp', 'w+'); + $this->loadContext(); + $cache = fopen('php://temp', 'w+'); + if ($cache === false) { + return false; + } + $this->cache = $cache; return true; } diff --git a/apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php b/apps/files_external/3rdparty/icewind/streams/src/UrlCallback.php similarity index 79% rename from apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php rename to apps/files_external/3rdparty/icewind/streams/src/UrlCallback.php index 580bfc6ba221..02dca15f95ca 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/UrlCallBack.php +++ b/apps/files_external/3rdparty/icewind/streams/src/UrlCallback.php @@ -47,11 +47,10 @@ class UrlCallback extends Wrapper implements Url { * @return \Icewind\Streams\Path * * @throws \BadMethodCallException - * @throws \Exception */ public static function wrap($source, $fopen = null, $opendir = null, $mkdir = null, $rename = null, $rmdir = null, $unlink = null, $stat = null) { - $options = array( + return new Path(static::class, [ 'source' => $source, 'fopen' => $fopen, 'opendir' => $opendir, @@ -60,11 +59,10 @@ public static function wrap($source, $fopen = null, $opendir = null, $mkdir = nu 'rmdir' => $rmdir, 'unlink' => $unlink, 'stat' => $stat - ); - return new Path('\Icewind\Streams\UrlCallBack', $options); + ]); } - protected function loadContext($url) { + protected function loadUrlContext($url) { list($protocol) = explode('://', $url); $options = stream_context_get_options($this->context); return $options[$protocol]; @@ -77,40 +75,48 @@ protected function callCallBack($context, $callback) { } public function stream_open($path, $mode, $options, &$opened_path) { - $context = $this->loadContext($path); + $context = $this->loadUrlContext($path); $this->callCallBack($context, 'fopen'); - $this->setSourceStream(fopen($context['source'], $mode)); + $source = fopen($context['source'], $mode); + if ($source === false) { + return false; + } + $this->setSourceStream($source); return true; } public function dir_opendir($path, $options) { - $context = $this->loadContext($path); + $context = $this->loadUrlContext($path); $this->callCallBack($context, 'opendir'); - $this->setSourceStream(opendir($context['source'])); + $source = opendir($context['source']); + if ($source === false) { + return false; + } + $this->setSourceStream($source); return true; } public function mkdir($path, $mode, $options) { - $context = $this->loadContext($path); + $context = $this->loadUrlContext($path); $this->callCallBack($context, 'mkdir'); - return mkdir($context['source'], $mode, $options & STREAM_MKDIR_RECURSIVE); + return mkdir($context['source'], $mode, ($options & STREAM_MKDIR_RECURSIVE) > 0); } public function rmdir($path, $options) { - $context = $this->loadContext($path); + $context = $this->loadUrlContext($path); $this->callCallBack($context, 'rmdir'); return rmdir($context['source']); } public function rename($source, $target) { - $context = $this->loadContext($source); + $context = $this->loadUrlContext($source); $this->callCallBack($context, 'rename'); list(, $target) = explode('://', $target); return rename($context['source'], $target); } public function unlink($path) { - $context = $this->loadContext($path); + $context = $this->loadUrlContext($path); $this->callCallBack($context, 'unlink'); return unlink($context['source']); } diff --git a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php index 8e52eff9a085..abadab4dc4b7 100644 --- a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php +++ b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php @@ -12,7 +12,7 @@ * * This wrapper itself doesn't implement any functionality but is just a base class for other wrappers to extend */ -abstract class Wrapper implements File, Directory { +abstract class Wrapper extends WrapperHandler implements File, Directory { /** * @var resource */ @@ -25,36 +25,15 @@ abstract class Wrapper implements File, Directory { */ protected $source; - protected static function wrapSource($source, $context, $protocol, $class) { - try { - stream_wrapper_register($protocol, $class); - if (@rewinddir($source) === false) { - $wrapped = fopen($protocol . '://', 'r+', false, $context); - } else { - $wrapped = opendir($protocol . '://', $context); - } - } catch (\BadMethodCallException $e) { - stream_wrapper_unregister($protocol); - throw $e; - } - stream_wrapper_unregister($protocol); - return $wrapped; - } - /** - * Load the source from the stream context and return the context options - * - * @param string $name - * @return array - * @throws \Exception + * @param resource $source */ - protected function loadContext($name) { - $context = stream_context_get_options($this->context); - if (isset($context[$name])) { - $context = $context[$name]; - } else { - throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set'); - } + protected function setSourceStream($source) { + $this->source = $source; + } + + protected function loadContext($name = null) { + $context = parent::loadContext($name); if (isset($context['source']) and is_resource($context['source'])) { $this->setSourceStream($context['source']); } else { @@ -63,13 +42,6 @@ protected function loadContext($name) { return $context; } - /** - * @param resource $source - */ - protected function setSourceStream($source) { - $this->source = $source; - } - public function stream_seek($offset, $whence = SEEK_SET) { $result = fseek($this->source, $offset, $whence); return $result == 0 ? true : false; diff --git a/apps/files_external/3rdparty/icewind/streams/src/WrapperHandler.php b/apps/files_external/3rdparty/icewind/streams/src/WrapperHandler.php new file mode 100644 index 000000000000..72dc71485515 --- /dev/null +++ b/apps/files_external/3rdparty/icewind/streams/src/WrapperHandler.php @@ -0,0 +1,112 @@ + + * + * @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 . + * + */ + +namespace Icewind\Streams; + + +class WrapperHandler { + const NO_SOURCE_DIR = 1; + + /** + * get the protocol name that is generated for the class + * @param string|null $class + * @return string + */ + public static function getProtocol($class = null) { + if ($class === null) { + $class = static::class; + } + + $parts = explode('\\', $class); + return strtolower(array_pop($parts)); + } + + private static function buildContext($protocol, $context, $source) { + if (is_array($context)) { + $context['source'] = $source; + return stream_context_create([$protocol => $context]); + } else { + return $context; + } + } + + /** + * @param resource|int $source + * @param resource|array $context + * @param string|null $protocol deprecated, protocol is now automatically generated + * @param string|null $class deprecated, class is now automatically generated + * @return bool|resource + */ + protected static function wrapSource($source, $context = [], $protocol = null, $class = null) { + if ($class === null) { + $class = static::class; + } + + if ($protocol === null) { + $protocol = self::getProtocol($class); + } + + $context = self::buildContext($protocol, $context, $source); + try { + stream_wrapper_register($protocol, $class); + if (self::isDirectoryHandle($source)) { + return opendir($protocol . '://', $context); + } else { + return fopen($protocol . '://', 'r+', false, $context); + } + } finally { + stream_wrapper_unregister($protocol); + } + } + + protected static function isDirectoryHandle($resource) { + if ($resource === self::NO_SOURCE_DIR) { + return true; + } + if (!is_resource($resource)) { + throw new \BadMethodCallException('Invalid stream source'); + } + $meta = stream_get_meta_data($resource); + return $meta['stream_type'] === 'dir' || $meta['stream_type'] === 'user-space-dir'; + } + + /** + * Load the source from the stream context and return the context options + * + * @param string|null $name if not set, the generated protocol name is used + * @return array + * @throws \BadMethodCallException + */ + protected function loadContext($name = null) { + if ($name === null) { + $parts = explode('\\', static::class); + $name = strtolower(array_pop($parts)); + } + + $context = stream_context_get_options($this->context); + if (isset($context[$name])) { + $context = $context[$name]; + } else { + throw new \BadMethodCallException('Invalid context, "' . $name . '" options not set'); + } + return $context; + } +} diff --git a/apps/files_external/3rdparty/icewind/streams/src/WriteHashWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/WriteHashWrapper.php new file mode 100644 index 000000000000..854845ad19dd --- /dev/null +++ b/apps/files_external/3rdparty/icewind/streams/src/WriteHashWrapper.php @@ -0,0 +1,37 @@ + + * + * @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 . + * + */ + +namespace Icewind\Streams; + +/** + * Wrapper that calculates the hash on the stream on write + * + * The stream and hash should be passed in when wrapping the stream. + * On close the callback will be called with the calculated checksum. + * + * For supported hashes see: http://php.net/manual/en/function.hash-algos.php + */ +class WriteHashWrapper extends HashWrapper { + public function stream_write($data) { + $this->updateHash($data); + return parent::stream_write($data); + } +} \ No newline at end of file