summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/files/ajax/scan.php6
-rw-r--r--apps/files/appinfo/app.php7
-rw-r--r--apps/files/l10n/gl.js2
-rw-r--r--apps/files/l10n/gl.json2
-rw-r--r--apps/files/l10n/ja.js1
-rw-r--r--apps/files/l10n/ja.json1
-rw-r--r--apps/files/l10n/mr.js9
-rw-r--r--apps/files/l10n/mr.json7
-rw-r--r--apps/files/lib/activity.php278
-rw-r--r--apps/files_encryption/l10n/es.js10
-rw-r--r--apps/files_encryption/l10n/es.json10
-rw-r--r--apps/files_encryption/l10n/gl.js2
-rw-r--r--apps/files_encryption/l10n/gl.json2
-rw-r--r--apps/files_external/3rdparty/autoload.php7
-rw-r--r--apps/files_external/3rdparty/composer.json13
-rw-r--r--apps/files_external/3rdparty/composer.lock101
-rw-r--r--apps/files_external/3rdparty/composer/ClassLoader.php413
-rw-r--r--apps/files_external/3rdparty/composer/autoload_classmap.php9
-rw-r--r--apps/files_external/3rdparty/composer/autoload_namespaces.php9
-rw-r--r--apps/files_external/3rdparty/composer/autoload_psr4.php13
-rw-r--r--apps/files_external/3rdparty/composer/autoload_real.php50
-rw-r--r--apps/files_external/3rdparty/composer/installed.json87
-rw-r--r--apps/files_external/3rdparty/icewind/smb/.gitignore2
-rw-r--r--apps/files_external/3rdparty/icewind/smb/.travis.yml50
-rw-r--r--apps/files_external/3rdparty/icewind/smb/LICENSE.txt19
-rw-r--r--apps/files_external/3rdparty/icewind/smb/README.md136
-rw-r--r--apps/files_external/3rdparty/icewind/smb/composer.json24
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Connection.php78
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php28
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php11
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php11
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php31
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php11
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php10
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php11
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/FileInfo.php126
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php55
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/IShare.php134
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php142
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/NativeServer.php60
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/NativeShare.php288
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/NativeState.php308
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/NativeStream.php114
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Parser.php130
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/RawConnection.php165
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Server.php141
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Share.php394
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php534
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php27
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php143
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/Parser.php87
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/Server.php57
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/Share.php24
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php9
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/config.json7
-rw-r--r--apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml6
-rw-r--r--apps/files_external/3rdparty/icewind/streams/.gitignore3
-rw-r--r--apps/files_external/3rdparty/icewind/streams/.travis.yml26
-rw-r--r--apps/files_external/3rdparty/icewind/streams/README.md52
-rw-r--r--apps/files_external/3rdparty/icewind/streams/composer.json23
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php110
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/Directory.php35
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/File.php86
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php123
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php42
-rw-r--r--apps/files_external/3rdparty/icewind/streams/src/Wrapper.php110
-rw-r--r--apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php72
-rw-r--r--apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php130
-rw-r--r--apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php59
-rw-r--r--apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php105
-rw-r--r--apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php9
-rw-r--r--apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml6
-rw-r--r--apps/files_external/3rdparty/smb4php/smb.php516
-rw-r--r--apps/files_external/appinfo/app.php2
-rw-r--r--apps/files_external/l10n/cs_CZ.js2
-rw-r--r--apps/files_external/l10n/cs_CZ.json2
-rw-r--r--apps/files_external/l10n/gl.js2
-rw-r--r--apps/files_external/l10n/gl.json2
-rw-r--r--apps/files_external/l10n/ja.js2
-rw-r--r--apps/files_external/l10n/ja.json2
-rw-r--r--apps/files_external/lib/sftp.php12
-rw-r--r--apps/files_external/lib/smb.php294
-rw-r--r--apps/files_external/lib/smb_oc.php45
-rw-r--r--apps/files_external/tests/backends/ftp.php8
-rw-r--r--apps/files_external/tests/backends/smb.php15
-rw-r--r--apps/files_external/tests/backends/webdav.php2
-rwxr-xr-xapps/files_external/tests/env/start-ftp-morrisjobke.sh65
-rwxr-xr-xapps/files_external/tests/env/start-smb-silvershell.sh63
-rwxr-xr-xapps/files_external/tests/env/start-webdav-ownCloud.sh7
-rwxr-xr-xapps/files_external/tests/env/stop-ftp-morrisjobke.sh36
-rwxr-xr-xapps/files_external/tests/env/stop-smb-silvershell.sh36
-rwxr-xr-xapps/files_external/tests/env/stop-webdav-ownCloud.sh11
-rw-r--r--apps/files_external/tests/smbfunctions.php39
-rw-r--r--apps/files_sharing/appinfo/app.php5
-rw-r--r--apps/files_sharing/l10n/gl.js10
-rw-r--r--apps/files_sharing/l10n/gl.json10
-rw-r--r--apps/files_sharing/l10n/ja.js4
-rw-r--r--apps/files_sharing/l10n/ja.json4
-rw-r--r--apps/files_sharing/lib/activity.php214
-rw-r--r--apps/files_sharing/lib/controllers/sharecontroller.php48
-rw-r--r--apps/files_sharing/tests/activity.php12
-rw-r--r--apps/user_ldap/l10n/de.js12
-rw-r--r--apps/user_ldap/l10n/de.json12
-rw-r--r--apps/user_ldap/l10n/de_DE.js10
-rw-r--r--apps/user_ldap/l10n/de_DE.json10
-rw-r--r--apps/user_ldap/l10n/gl.js2
-rw-r--r--apps/user_ldap/l10n/gl.json2
-rw-r--r--apps/user_ldap/l10n/mr.js7
-rw-r--r--apps/user_ldap/l10n/mr.json5
-rw-r--r--apps/user_webdavauth/l10n/de.js2
-rw-r--r--apps/user_webdavauth/l10n/de.json2
122 files changed, 6209 insertions, 838 deletions
diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php
index 89641f1890b..7daae26d1db 100644
--- a/apps/files/ajax/scan.php
+++ b/apps/files/ajax/scan.php
@@ -1,11 +1,15 @@
<?php
set_time_limit(0); //scanning can take ages
+
+\OCP\JSON::checkLoggedIn();
+\OCP\JSON::callCheck();
+
\OC::$server->getSession()->close();
$force = (isset($_GET['force']) and ($_GET['force'] === 'true'));
$dir = isset($_GET['dir']) ? (string)$_GET['dir'] : '';
if (isset($_GET['users'])) {
- OC_JSON::checkAdminUser();
+ \OCP\JSON::checkAdminUser();
if ($_GET['users'] === 'all') {
$users = OC_User::getUsers();
} else {
diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php
index 62c205add52..87791e2558e 100644
--- a/apps/files/appinfo/app.php
+++ b/apps/files/appinfo/app.php
@@ -27,3 +27,10 @@ $templateManager->registerTemplate('application/vnd.oasis.opendocument.spreadshe
"name" => $l->t('All files')
)
);
+
+\OC::$server->getActivityManager()->registerExtension(function() {
+ return new \OCA\Files\Activity(
+ \OC::$server->query('L10NFactory'),
+ \OC::$server->getURLGenerator()
+ );
+});
diff --git a/apps/files/l10n/gl.js b/apps/files/l10n/gl.js
index ffd897981f3..6d4a863f7df 100644
--- a/apps/files/l10n/gl.js
+++ b/apps/files/l10n/gl.js
@@ -79,7 +79,7 @@ OC.L10N.register(
"{dirs} and {files}" : "{dirs} e {files}",
"Favorited" : "Marcado como favorito",
"Favorite" : "Favorito",
- "An error occurred while trying to update the tags" : "Houbo un erro ao tentar actualizar as etiquetas",
+ "An error occurred while trying to update the tags" : "Produciuse un erro ao tentar actualizar as etiquetas",
"%s could not be renamed as it has been deleted" : "Non é posíbel renomear %s xa que foi eliminado",
"%s could not be renamed" : "%s non pode cambiar de nome",
"Upload (max. %s)" : "Envío (máx. %s)",
diff --git a/apps/files/l10n/gl.json b/apps/files/l10n/gl.json
index d5ba50053c4..6cfaf9f39d0 100644
--- a/apps/files/l10n/gl.json
+++ b/apps/files/l10n/gl.json
@@ -77,7 +77,7 @@
"{dirs} and {files}" : "{dirs} e {files}",
"Favorited" : "Marcado como favorito",
"Favorite" : "Favorito",
- "An error occurred while trying to update the tags" : "Houbo un erro ao tentar actualizar as etiquetas",
+ "An error occurred while trying to update the tags" : "Produciuse un erro ao tentar actualizar as etiquetas",
"%s could not be renamed as it has been deleted" : "Non é posíbel renomear %s xa que foi eliminado",
"%s could not be renamed" : "%s non pode cambiar de nome",
"Upload (max. %s)" : "Envío (máx. %s)",
diff --git a/apps/files/l10n/ja.js b/apps/files/l10n/ja.js
index 0cb3193c61d..1d8026e2139 100644
--- a/apps/files/l10n/ja.js
+++ b/apps/files/l10n/ja.js
@@ -79,6 +79,7 @@ OC.L10N.register(
"{dirs} and {files}" : "{dirs} と {files}",
"Favorited" : "お気に入り済",
"Favorite" : "お気に入り",
+ "An error occurred while trying to update the tags" : "タグを更新する際にエラーが発生しました",
"%s could not be renamed as it has been deleted" : "%s は削除されたため、ファイル名を変更できません",
"%s could not be renamed" : "%sの名前を変更できませんでした",
"Upload (max. %s)" : "アップロード ( 最大 %s )",
diff --git a/apps/files/l10n/ja.json b/apps/files/l10n/ja.json
index 570b63ab5f7..8d758fb5037 100644
--- a/apps/files/l10n/ja.json
+++ b/apps/files/l10n/ja.json
@@ -77,6 +77,7 @@
"{dirs} and {files}" : "{dirs} と {files}",
"Favorited" : "お気に入り済",
"Favorite" : "お気に入り",
+ "An error occurred while trying to update the tags" : "タグを更新する際にエラーが発生しました",
"%s could not be renamed as it has been deleted" : "%s は削除されたため、ファイル名を変更できません",
"%s could not be renamed" : "%sの名前を変更できませんでした",
"Upload (max. %s)" : "アップロード ( 最大 %s )",
diff --git a/apps/files/l10n/mr.js b/apps/files/l10n/mr.js
new file mode 100644
index 00000000000..7988332fa91
--- /dev/null
+++ b/apps/files/l10n/mr.js
@@ -0,0 +1,9 @@
+OC.L10N.register(
+ "files",
+ {
+ "_%n folder_::_%n folders_" : ["",""],
+ "_%n file_::_%n files_" : ["",""],
+ "_Uploading %n file_::_Uploading %n files_" : ["",""],
+ "_matches '{filter}'_::_match '{filter}'_" : ["",""]
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/files/l10n/mr.json b/apps/files/l10n/mr.json
new file mode 100644
index 00000000000..ef5fc586755
--- /dev/null
+++ b/apps/files/l10n/mr.json
@@ -0,0 +1,7 @@
+{ "translations": {
+ "_%n folder_::_%n folders_" : ["",""],
+ "_%n file_::_%n files_" : ["",""],
+ "_Uploading %n file_::_Uploading %n files_" : ["",""],
+ "_matches '{filter}'_::_match '{filter}'_" : ["",""]
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/files/lib/activity.php b/apps/files/lib/activity.php
new file mode 100644
index 00000000000..be7acbc3c07
--- /dev/null
+++ b/apps/files/lib/activity.php
@@ -0,0 +1,278 @@
+<?php
+/**
+ * ownCloud - Files Activity Extension
+ *
+ * @author Joas Schilling
+ * @copyright 2015 Joas Schilling nickvergessen@owncloud.com
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OCA\Files;
+
+use OC\L10N\Factory;
+use OCP\Activity\IExtension;
+use OCP\IL10N;
+use OCP\IURLGenerator;
+
+class Activity implements IExtension {
+ const FILTER_FILES = 'files';
+
+ const TYPE_SHARE_CREATED = 'file_created';
+ const TYPE_SHARE_CHANGED = 'file_changed';
+ const TYPE_SHARE_DELETED = 'file_deleted';
+ const TYPE_SHARE_RESTORED = 'file_restored';
+
+ /** @var IL10N */
+ protected $l;
+
+ /** @var Factory */
+ protected $languageFactory;
+
+ /** @var IURLGenerator */
+ protected $URLGenerator;
+
+ /**
+ * @param Factory $languageFactory
+ * @param IURLGenerator $URLGenerator
+ */
+ public function __construct(Factory $languageFactory, IURLGenerator $URLGenerator) {
+ $this->languageFactory = $languageFactory;
+ $this->URLGenerator = $URLGenerator;
+ $this->l = $this->getL10N();
+ }
+
+ /**
+ * @param string|null $languageCode
+ * @return IL10N
+ */
+ protected function getL10N($languageCode = null) {
+ return $this->languageFactory->get('files', $languageCode);
+ }
+
+ /**
+ * The extension can return an array of additional notification types.
+ * If no additional types are to be added false is to be returned
+ *
+ * @param string $languageCode
+ * @return array|false
+ */
+ public function getNotificationTypes($languageCode) {
+ $l = $this->getL10N($languageCode);
+ return [
+ self::TYPE_SHARE_CREATED => (string) $l->t('A new file or folder has been <strong>created</strong>'),
+ self::TYPE_SHARE_CHANGED => (string) $l->t('A file or folder has been <strong>changed</strong>'),
+ self::TYPE_SHARE_DELETED => (string) $l->t('A file or folder has been <strong>deleted</strong>'),
+ self::TYPE_SHARE_RESTORED => (string) $l->t('A file or folder has been <strong>restored</strong>'),
+ ];
+ }
+
+ /**
+ * For a given method additional types to be displayed in the settings can be returned.
+ * In case no additional types are to be added false is to be returned.
+ *
+ * @param string $method
+ * @return array|false
+ */
+ public function getDefaultTypes($method) {
+ if ($method === 'stream') {
+ $settings = array();
+ $settings[] = self::TYPE_SHARE_CREATED;
+ $settings[] = self::TYPE_SHARE_CHANGED;
+ $settings[] = self::TYPE_SHARE_DELETED;
+ $settings[] = self::TYPE_SHARE_RESTORED;
+ return $settings;
+ }
+
+ return false;
+ }
+
+ /**
+ * The extension can translate a given message to the requested languages.
+ * If no translation is available false is to be returned.
+ *
+ * @param string $app
+ * @param string $text
+ * @param array $params
+ * @param boolean $stripPath
+ * @param boolean $highlightParams
+ * @param string $languageCode
+ * @return string|false
+ */
+ public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
+ if ($app !== 'files') {
+ return false;
+ }
+
+ switch ($text) {
+ case 'created_self':
+ return (string) $this->l->t('You created %1$s', $params);
+ case 'created_by':
+ return (string) $this->l->t('%2$s created %1$s', $params);
+ case 'created_public':
+ return (string) $this->l->t('%1$s was created in a public folder', $params);
+ case 'changed_self':
+ return (string) $this->l->t('You changed %1$s', $params);
+ case 'changed_by':
+ return (string) $this->l->t('%2$s changed %1$s', $params);
+ case 'deleted_self':
+ return (string) $this->l->t('You deleted %1$s', $params);
+ case 'deleted_by':
+ return (string) $this->l->t('%2$s deleted %1$s', $params);
+ case 'restored_self':
+ return (string) $this->l->t('You restored %1$s', $params);
+ case 'restored_by':
+ return (string) $this->l->t('%2$s restored %1$s', $params);
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * The extension can define the type of parameters for translation
+ *
+ * Currently known types are:
+ * * file => will strip away the path of the file and add a tooltip with it
+ * * username => will add the avatar of the user
+ *
+ * @param string $app
+ * @param string $text
+ * @return array|false
+ */
+ function getSpecialParameterList($app, $text) {
+ if ($app === 'files') {
+ switch ($text) {
+ case 'created_self':
+ case 'created_by':
+ case 'created_public':
+ case 'changed_self':
+ case 'changed_by':
+ case 'deleted_self':
+ case 'deleted_by':
+ case 'restored_self':
+ case 'restored_by':
+ return [
+ 0 => 'file',
+ 1 => 'username',
+ ];
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * A string naming the css class for the icon to be used can be returned.
+ * If no icon is known for the given type false is to be returned.
+ *
+ * @param string $type
+ * @return string|false
+ */
+ public function getTypeIcon($type) {
+ switch ($type) {
+ case self::TYPE_SHARE_CHANGED:
+ return 'icon-change';
+ case self::TYPE_SHARE_CREATED:
+ return 'icon-add-color';
+ case self::TYPE_SHARE_DELETED:
+ return 'icon-delete-color';
+
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * The extension can define the parameter grouping by returning the index as integer.
+ * In case no grouping is required false is to be returned.
+ *
+ * @param array $activity
+ * @return integer|false
+ */
+ public function getGroupParameter($activity) {
+ if ($activity['app'] === 'files') {
+ switch ($activity['subject']) {
+ case 'created_self':
+ case 'created_by':
+ case 'changed_self':
+ case 'changed_by':
+ case 'deleted_self':
+ case 'deleted_by':
+ case 'restored_self':
+ case 'restored_by':
+ return 0;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * The extension can define additional navigation entries. The array returned has to contain two keys 'top'
+ * and 'apps' which hold arrays with the relevant entries.
+ * If no further entries are to be added false is no be returned.
+ *
+ * @return array|false
+ */
+ public function getNavigation() {
+ return [
+ 'apps' => [
+ self::FILTER_FILES => [
+ 'id' => self::FILTER_FILES,
+ 'name' => (string) $this->l->t('Files'),
+ 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::FILTER_FILES]),
+ ],
+ ],
+ 'top' => [],
+ ];
+ }
+
+ /**
+ * The extension can check if a customer filter (given by a query string like filter=abc) is valid or not.
+ *
+ * @param string $filterValue
+ * @return boolean
+ */
+ public function isFilterValid($filterValue) {
+ return $filterValue === self::FILTER_FILES;
+ }
+
+ /**
+ * The extension can filter the types based on the filter if required.
+ * In case no filter is to be applied false is to be returned unchanged.
+ *
+ * @param array $types
+ * @param string $filter
+ * @return array|false
+ */
+ public function filterNotificationTypes($types, $filter) {
+ if ($filter === self::FILTER_FILES) {
+ return array_intersect([
+ self::TYPE_SHARE_CREATED,
+ self::TYPE_SHARE_CHANGED,
+ self::TYPE_SHARE_DELETED,
+ self::TYPE_SHARE_RESTORED,
+ ], $types);
+ }
+ return false;
+ }
+
+ /**
+ * For a given filter the extension can specify the sql query conditions including parameters for that query.
+ * In case the extension does not know the filter false is to be returned.
+ * The query condition and the parameters are to be returned as array with two elements.
+ * E.g. return array('`app` = ? and `message` like ?', array('mail', 'ownCloud%'));
+ *
+ * @param string $filter
+ * @return array|false
+ */
+ public function getQueryForFilter($filter) {
+ if ($filter === self::FILTER_FILES) {
+ return ['`app` = ?', ['files']];
+ }
+ return false;
+ }
+}
diff --git a/apps/files_encryption/l10n/es.js b/apps/files_encryption/l10n/es.js
index 40d01773017..a586f4d73b8 100644
--- a/apps/files_encryption/l10n/es.js
+++ b/apps/files_encryption/l10n/es.js
@@ -13,24 +13,24 @@ OC.L10N.register(
"Please repeat the new recovery password" : "Por favor repita su nueva contraseña de recuperacion",
"Password successfully changed." : "Su contraseña ha sido cambiada",
"Could not change the password. Maybe the old password was not correct." : "No se pudo cambiar la contraseña. Compruebe que la contraseña actual sea correcta.",
- "Could not update the private key password." : "No se pudo actualizar la contraseña de clave privada.",
+ "Could not update the private key password." : "No se pudo actualizar la contraseña de la clave privada.",
"The old password was not correct, please try again." : "La antigua contraseña no es correcta, por favor intente de nuevo.",
"The current log-in password was not correct, please try again." : "La contraseña de inicio de sesión actual no es correcto, por favor intente de nuevo.",
"Private key password successfully updated." : "Contraseña de clave privada actualizada con éxito.",
"File recovery settings updated" : "Opciones de recuperación de archivos actualizada",
"Could not update file recovery" : "No se pudo actualizar la recuperación de archivos",
"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." : "¡La aplicación de cifrado no ha sido inicializada! Quizá se restableció durante su sesión. Por favor intente cerrar la sesión y volver a iniciarla para inicializar la aplicación de cifrado.",
- "Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." : "¡Su clave privada no es válida! Tal vez su contraseña ha sido cambiada desde fuera. de %s (Ej:Su directorio corporativo). Puede actualizar la contraseña de su clave privada en sus opciones personales para recuperar el acceso a sus archivos.",
+ "Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." : "¡Su clave privada no es válida! Tal vez su contraseña ha sido cambiada desde fuera de %s (Ej: Su directorio corporativo). Puede actualizar la contraseña de su clave privada en sus opciones personales para recuperar el acceso a sus archivos.",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "No fue posible descifrar este archivo, probablemente se trate de un archivo compartido. Solicite al propietario del mismo que vuelva a compartirlo con usted.",
- "Unknown error. Please check your system settings or contact your administrator" : "Error desconocido. Revise la configuración de su sistema o contacte a su administrador",
- "Initial encryption started... This can take some time. Please wait." : "Encriptación iniciada..... Esto puede tomar un tiempo. Por favor espere.",
+ "Unknown error. Please check your system settings or contact your administrator" : "Error desconocido. Revise la configuración de su sistema o contacte con su administrador",
+ "Initial encryption started... This can take some time. Please wait." : "Ha comenzado el cifrado inicial... Esto puede tardar un rato. Por favor espere.",
"Initial encryption running... Please try again later." : "Cifrado inicial en curso... Inténtelo más tarde.",
"Missing requirements." : "Requisitos incompletos.",
"Please make sure that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." : "Asegúrese de que OpenSSL y la extensión de PHP estén habilitados y configurados correctamente. Por el momento, la aplicación de cifrado ha sido deshabilitada.",
"Following users are not set up for encryption:" : "Los siguientes usuarios no han sido configurados para el cifrado:",
"Go directly to your %spersonal settings%s." : "Ir directamente a %sOpciones%s.",
"Server-side Encryption" : "Cifrado en el servidor",
- "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "La app de crifrado está habilitada pero sus claves no han sido inicializadas, por favor, cierre la sesión y vuelva a iniciarla de nuevo.",
+ "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "La app de cifrado está habilitada pero sus claves no se han inicializado, por favor, cierre la sesión y vuelva a iniciarla de nuevo.",
"Enable recovery key (allow to recover users files in case of password loss):" : "Habilitar la clave de recuperación (permite recuperar los ficheros del usuario en caso de pérdida de la contraseña);",
"Recovery key password" : "Contraseña de clave de recuperación",
"Repeat Recovery key password" : "Repite la contraseña de clave de recuperación",
diff --git a/apps/files_encryption/l10n/es.json b/apps/files_encryption/l10n/es.json
index d2fc38f135a..e2b9ace05f6 100644
--- a/apps/files_encryption/l10n/es.json
+++ b/apps/files_encryption/l10n/es.json
@@ -11,24 +11,24 @@
"Please repeat the new recovery password" : "Por favor repita su nueva contraseña de recuperacion",
"Password successfully changed." : "Su contraseña ha sido cambiada",
"Could not change the password. Maybe the old password was not correct." : "No se pudo cambiar la contraseña. Compruebe que la contraseña actual sea correcta.",
- "Could not update the private key password." : "No se pudo actualizar la contraseña de clave privada.",
+ "Could not update the private key password." : "No se pudo actualizar la contraseña de la clave privada.",
"The old password was not correct, please try again." : "La antigua contraseña no es correcta, por favor intente de nuevo.",
"The current log-in password was not correct, please try again." : "La contraseña de inicio de sesión actual no es correcto, por favor intente de nuevo.",
"Private key password successfully updated." : "Contraseña de clave privada actualizada con éxito.",
"File recovery settings updated" : "Opciones de recuperación de archivos actualizada",
"Could not update file recovery" : "No se pudo actualizar la recuperación de archivos",
"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." : "¡La aplicación de cifrado no ha sido inicializada! Quizá se restableció durante su sesión. Por favor intente cerrar la sesión y volver a iniciarla para inicializar la aplicación de cifrado.",
- "Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." : "¡Su clave privada no es válida! Tal vez su contraseña ha sido cambiada desde fuera. de %s (Ej:Su directorio corporativo). Puede actualizar la contraseña de su clave privada en sus opciones personales para recuperar el acceso a sus archivos.",
+ "Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." : "¡Su clave privada no es válida! Tal vez su contraseña ha sido cambiada desde fuera de %s (Ej: Su directorio corporativo). Puede actualizar la contraseña de su clave privada en sus opciones personales para recuperar el acceso a sus archivos.",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "No fue posible descifrar este archivo, probablemente se trate de un archivo compartido. Solicite al propietario del mismo que vuelva a compartirlo con usted.",
- "Unknown error. Please check your system settings or contact your administrator" : "Error desconocido. Revise la configuración de su sistema o contacte a su administrador",
- "Initial encryption started... This can take some time. Please wait." : "Encriptación iniciada..... Esto puede tomar un tiempo. Por favor espere.",
+ "Unknown error. Please check your system settings or contact your administrator" : "Error desconocido. Revise la configuración de su sistema o contacte con su administrador",
+ "Initial encryption started... This can take some time. Please wait." : "Ha comenzado el cifrado inicial... Esto puede tardar un rato. Por favor espere.",
"Initial encryption running... Please try again later." : "Cifrado inicial en curso... Inténtelo más tarde.",
"Missing requirements." : "Requisitos incompletos.",
"Please make sure that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." : "Asegúrese de que OpenSSL y la extensión de PHP estén habilitados y configurados correctamente. Por el momento, la aplicación de cifrado ha sido deshabilitada.",
"Following users are not set up for encryption:" : "Los siguientes usuarios no han sido configurados para el cifrado:",
"Go directly to your %spersonal settings%s." : "Ir directamente a %sOpciones%s.",
"Server-side Encryption" : "Cifrado en el servidor",
- "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "La app de crifrado está habilitada pero sus claves no han sido inicializadas, por favor, cierre la sesión y vuelva a iniciarla de nuevo.",
+ "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "La app de cifrado está habilitada pero sus claves no se han inicializado, por favor, cierre la sesión y vuelva a iniciarla de nuevo.",
"Enable recovery key (allow to recover users files in case of password loss):" : "Habilitar la clave de recuperación (permite recuperar los ficheros del usuario en caso de pérdida de la contraseña);",
"Recovery key password" : "Contraseña de clave de recuperación",
"Repeat Recovery key password" : "Repite la contraseña de clave de recuperación",
diff --git a/apps/files_encryption/l10n/gl.js b/apps/files_encryption/l10n/gl.js
index 6e9983159fd..b9654e5b25e 100644
--- a/apps/files_encryption/l10n/gl.js
+++ b/apps/files_encryption/l10n/gl.js
@@ -10,7 +10,7 @@ OC.L10N.register(
"Recovery key successfully disabled" : "Desactivada satisfactoriamente a chave de recuperación",
"Please provide the old recovery password" : "Introduza a chave de recuperación antiga",
"Please provide a new recovery password" : "Introduza a nova chave de recuperación",
- "Please repeat the new recovery password" : "Por favor repita a nova chave de recuperación",
+ "Please repeat the new recovery password" : "Repita a nova chave de recuperación",
"Password successfully changed." : "O contrasinal foi cambiado satisfactoriamente",
"Could not change the password. Maybe the old password was not correct." : "Non foi posíbel cambiar o contrasinal. Probabelmente o contrasinal antigo non é o correcto.",
"Could not update the private key password." : "Non foi posíbel actualizar o contrasinal da chave privada.",
diff --git a/apps/files_encryption/l10n/gl.json b/apps/files_encryption/l10n/gl.json
index 6295f339253..6c484fad83a 100644
--- a/apps/files_encryption/l10n/gl.json
+++ b/apps/files_encryption/l10n/gl.json
@@ -8,7 +8,7 @@
"Recovery key successfully disabled" : "Desactivada satisfactoriamente a chave de recuperación",
"Please provide the old recovery password" : "Introduza a chave de recuperación antiga",
"Please provide a new recovery password" : "Introduza a nova chave de recuperación",
- "Please repeat the new recovery password" : "Por favor repita a nova chave de recuperación",
+ "Please repeat the new recovery password" : "Repita a nova chave de recuperación",
"Password successfully changed." : "O contrasinal foi cambiado satisfactoriamente",
"Could not change the password. Maybe the old password was not correct." : "Non foi posíbel cambiar o contrasinal. Probabelmente o contrasinal antigo non é o correcto.",
"Could not update the private key password." : "Non foi posíbel actualizar o contrasinal da chave privada.",
diff --git a/apps/files_external/3rdparty/autoload.php b/apps/files_external/3rdparty/autoload.php
new file mode 100644
index 00000000000..78e3de4ca0c
--- /dev/null
+++ b/apps/files_external/3rdparty/autoload.php
@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer' . '/autoload_real.php';
+
+return ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3::getLoader();
diff --git a/apps/files_external/3rdparty/composer.json b/apps/files_external/3rdparty/composer.json
new file mode 100644
index 00000000000..b1315651c99
--- /dev/null
+++ b/apps/files_external/3rdparty/composer.json
@@ -0,0 +1,13 @@
+{
+ "name": "files_external/3rdparty",
+ "description": "3rdparty components for files_external",
+ "license": "MIT",
+ "config": {
+ "vendor-dir": "."
+ },
+ "require": {
+ "icewind/smb": "dev-master",
+ "icewind/streams": "0.2"
+ }
+}
+
diff --git a/apps/files_external/3rdparty/composer.lock b/apps/files_external/3rdparty/composer.lock
new file mode 100644
index 00000000000..3da75b2a900
--- /dev/null
+++ b/apps/files_external/3rdparty/composer.lock
@@ -0,0 +1,101 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "c854ee7f5bdcb3f2c8ee0a8cfe5e193a",
+ "packages": [
+ {
+ "name": "icewind/smb",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/icewind1991/SMB.git",
+ "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/icewind1991/SMB/zipball/ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+ "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+ "shasum": ""
+ },
+ "require": {
+ "icewind/streams": "0.2.x",
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "satooshi/php-coveralls": "dev-master"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Icewind\\SMB\\": "src/",
+ "Icewind\\SMB\\Test\\": "tests/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Robin Appelman",
+ "email": "icewind@owncloud.com"
+ }
+ ],
+ "description": "php wrapper for smbclient and libsmbclient-php",
+ "time": "2015-02-10 16:37:37"
+ },
+ {
+ "name": "icewind/streams",
+ "version": "0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/icewind1991/Streams.git",
+ "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/icewind1991/Streams/zipball/5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+ "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "satooshi/php-coveralls": "dev-master"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Icewind\\Streams\\Tests\\": "tests/",
+ "Icewind\\Streams\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Robin Appelman",
+ "email": "icewind@owncloud.com"
+ }
+ ],
+ "description": "A set of generic stream wrappers",
+ "time": "2014-07-30 23:46:15"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {
+ "icewind/smb": 20
+ },
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": []
+}
diff --git a/apps/files_external/3rdparty/composer/ClassLoader.php b/apps/files_external/3rdparty/composer/ClassLoader.php
new file mode 100644
index 00000000000..5e1469e8307
--- /dev/null
+++ b/apps/files_external/3rdparty/composer/ClassLoader.php
@@ -0,0 +1,413 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0 class loader
+ *
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class ClassLoader
+{
+ // PSR-4
+ private $prefixLengthsPsr4 = array();
+ private $prefixDirsPsr4 = array();
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ private $prefixesPsr0 = array();
+ private $fallbackDirsPsr0 = array();
+
+ private $useIncludePath = false;
+ private $classMap = array();
+
+ private $classMapAuthoritative = false;
+
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
+ }
+
+ return array();
+ }
+
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ (array) $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-0 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ (array) $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ (array) $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ (array) $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ (array) $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param array|string $paths The PSR-0 base directories
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param array|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return bool|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ includeFile($file);
+
+ return true;
+ }
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
+ if ('\\' == $class[0]) {
+ $class = substr($class, 1);
+ }
+
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative) {
+ return false;
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if ($file === null && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if ($file === null) {
+ // Remember that this class does not exist.
+ return $this->classMap[$class] = false;
+ }
+
+ return $file;
+ }
+
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+ }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+ include $file;
+}
diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php
new file mode 100644
index 00000000000..1bd6482f9ea
--- /dev/null
+++ b/apps/files_external/3rdparty/composer/autoload_classmap.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = $vendorDir;
+
+return array(
+);
diff --git a/apps/files_external/3rdparty/composer/autoload_namespaces.php b/apps/files_external/3rdparty/composer/autoload_namespaces.php
new file mode 100644
index 00000000000..71c9e91858d
--- /dev/null
+++ b/apps/files_external/3rdparty/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = $vendorDir;
+
+return array(
+);
diff --git a/apps/files_external/3rdparty/composer/autoload_psr4.php b/apps/files_external/3rdparty/composer/autoload_psr4.php
new file mode 100644
index 00000000000..7cfe0f1c46d
--- /dev/null
+++ b/apps/files_external/3rdparty/composer/autoload_psr4.php
@@ -0,0 +1,13 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(__FILE__));
+$baseDir = $vendorDir;
+
+return array(
+ 'Icewind\\Streams\\Tests\\' => array($vendorDir . '/icewind/streams/tests'),
+ 'Icewind\\Streams\\' => array($vendorDir . '/icewind/streams/src'),
+ 'Icewind\\SMB\\Test\\' => array($vendorDir . '/icewind/smb/tests'),
+ 'Icewind\\SMB\\' => array($vendorDir . '/icewind/smb/src'),
+);
diff --git a/apps/files_external/3rdparty/composer/autoload_real.php b/apps/files_external/3rdparty/composer/autoload_real.php
new file mode 100644
index 00000000000..3391b322be0
--- /dev/null
+++ b/apps/files_external/3rdparty/composer/autoload_real.php
@@ -0,0 +1,50 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3
+{
+ private static $loader;
+
+ public static function loadClassLoader($class)
+ {
+ if ('Composer\Autoload\ClassLoader' === $class) {
+ require __DIR__ . '/ClassLoader.php';
+ }
+ }
+
+ public static function getLoader()
+ {
+ if (null !== self::$loader) {
+ return self::$loader;
+ }
+
+ spl_autoload_register(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'), true, true);
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+ spl_autoload_unregister(array('ComposerAutoloaderInit98fe9b281934250b3a93f69a5ce843b3', 'loadClassLoader'));
+
+ $map = require __DIR__ . '/autoload_namespaces.php';
+ foreach ($map as $namespace => $path) {
+ $loader->set($namespace, $path);
+ }
+
+ $map = require __DIR__ . '/autoload_psr4.php';
+ foreach ($map as $namespace => $path) {
+ $loader->setPsr4($namespace, $path);
+ }
+
+ $classMap = require __DIR__ . '/autoload_classmap.php';
+ if ($classMap) {
+ $loader->addClassMap($classMap);
+ }
+
+ $loader->register(true);
+
+ return $loader;
+ }
+}
+
+function composerRequire98fe9b281934250b3a93f69a5ce843b3($file)
+{
+ require $file;
+}
diff --git a/apps/files_external/3rdparty/composer/installed.json b/apps/files_external/3rdparty/composer/installed.json
new file mode 100644
index 00000000000..03bad8abf36
--- /dev/null
+++ b/apps/files_external/3rdparty/composer/installed.json
@@ -0,0 +1,87 @@
+[
+ {
+ "name": "icewind/streams",
+ "version": "0.2",
+ "version_normalized": "0.2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/icewind1991/Streams.git",
+ "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/icewind1991/Streams/zipball/5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+ "reference": "5aae45f2ddd3d1a6e2a496dd5d1e7857bfeb605a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "satooshi/php-coveralls": "dev-master"
+ },
+ "time": "2014-07-30 23:46:15",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "Icewind\\Streams\\Tests\\": "tests/",
+ "Icewind\\Streams\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Robin Appelman",
+ "email": "icewind@owncloud.com"
+ }
+ ],
+ "description": "A set of generic stream wrappers"
+ },
+ {
+ "name": "icewind/smb",
+ "version": "dev-master",
+ "version_normalized": "9999999-dev",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/icewind1991/SMB.git",
+ "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/icewind1991/SMB/zipball/ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+ "reference": "ededbfbaa3d7124ce8d4b6c119cd225fa342916d",
+ "shasum": ""
+ },
+ "require": {
+ "icewind/streams": "0.2.x",
+ "php": ">=5.3"
+ },
+ "require-dev": {
+ "satooshi/php-coveralls": "dev-master"
+ },
+ "time": "2015-02-10 16:37:37",
+ "type": "library",
+ "installation-source": "source",
+ "autoload": {
+ "psr-4": {
+ "Icewind\\SMB\\": "src/",
+ "Icewind\\SMB\\Test\\": "tests/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Robin Appelman",
+ "email": "icewind@owncloud.com"
+ }
+ ],
+ "description": "php wrapper for smbclient and libsmbclient-php"
+ }
+]
diff --git a/apps/files_external/3rdparty/icewind/smb/.gitignore b/apps/files_external/3rdparty/icewind/smb/.gitignore
new file mode 100644
index 00000000000..3ce5adbbde5
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/.gitignore
@@ -0,0 +1,2 @@
+.idea
+vendor
diff --git a/apps/files_external/3rdparty/icewind/smb/.travis.yml b/apps/files_external/3rdparty/icewind/smb/.travis.yml
new file mode 100644
index 00000000000..c1ac3727d08
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/.travis.yml
@@ -0,0 +1,50 @@
+language: php
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+
+env:
+ global:
+ - CURRENT_DIR=`pwd`
+
+before_install:
+ - pass=$(perl -e 'print crypt("test", "password")')
+ - sudo useradd -m -p $pass test
+ - sudo apt-get update -qq
+ - sudo apt-get install samba smbclient libsmbclient-dev libsmbclient
+ - wget -O /tmp/libsmbclient-php.zip https://github.com/eduardok/libsmbclient-php/archive/master.zip
+ - unzip /tmp/libsmbclient-php.zip -d /tmp
+ - cd /tmp/libsmbclient-php-master
+ - phpize && ./configure && make && sudo make install
+ - echo 'extension="libsmbclient.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+ - cd $CURRENT_DIR
+ - chmod go+w $HOME
+ - printf "%s\n%s\n" test test|sudo smbpasswd -s test
+ - sudo mkdir /home/test/test
+ - sudo chown test /home/test/test
+ - |
+ echo "[test]
+ comment = test
+ path = /home/test
+ guest ok = yes
+ writeable = yes
+ map archive = yes
+ map system = yes
+ map hidden = yes
+ create mask = 0777
+ inherit permissions = yes" | sudo tee -a /etc/samba/smb.conf
+ - sudo service smbd restart
+ - testparm -s
+
+install:
+ - composer install --dev --no-interaction
+
+script:
+ - mkdir -p build/logs
+ - cd tests
+ - phpunit --coverage-clover ../build/logs/clover.xml --configuration phpunit.xml
+
+after_script:
+ - cd $CURRENT_DIR
+ - php vendor/bin/coveralls -v
diff --git a/apps/files_external/3rdparty/icewind/smb/LICENSE.txt b/apps/files_external/3rdparty/icewind/smb/LICENSE.txt
new file mode 100644
index 00000000000..16e3a1004ec
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/LICENSE.txt
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+
+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/icewind/smb/README.md b/apps/files_external/3rdparty/icewind/smb/README.md
new file mode 100644
index 00000000000..a0864717b09
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/README.md
@@ -0,0 +1,136 @@
+SMB
+===
+
+[![Coverage Status](https://img.shields.io/coveralls/icewind1991/SMB.svg)](https://coveralls.io/r/icewind1991/SMB?branch=master)
+[![Build Status](https://travis-ci.org/icewind1991/SMB.svg?branch=master)](https://travis-ci.org/icewind1991/SMB)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/icewind1991/SMB/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/icewind1991/SMB/?branch=master)
+
+PHP wrapper for `smbclient` and [`libsmbclient-php`](https://github.com/eduardok/libsmbclient-php)
+
+- Reuses a single `smbclient` instance for multiple requests
+- Doesn't leak the password to the process list
+- Simple 1-on-1 mapping of SMB commands
+- A stream-based api to remove the need for temporary files
+- Support for using libsmbclient directly trough [`libsmbclient-php`](https://github.com/eduardok/libsmbclient-php)
+
+Examples
+----
+
+### Upload a file ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$fileToUpload = __FILE__;
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+$share->put($fileToUpload, 'example.txt');
+```
+
+### Download a file ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$target = __DIR__ . '/target.txt';
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+$share->get('example.txt', $target);
+```
+
+### List shares on the remote server ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$shares = $server->listShares();
+
+foreach ($shares as $share) {
+ echo $share->getName() . "\n";
+}
+```
+
+### List the content of a folder ###
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+$content = $share->dir('test');
+
+foreach ($content as $info) {
+ echo $name->getName() . "\n";
+ echo "\tsize :" . $info->getSize() . "\n";
+}
+```
+
+### Using read streams
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+
+$fh = $share->read('test.txt');
+echo fread($fh, 4086);
+fclose($fh);
+```
+
+### Using write streams
+
+```php
+<?php
+use Icewind\SMB\Server;
+
+require('vendor/autoload.php');
+
+$server = new Server('localhost', 'test', 'test');
+$share = $server->getShare('test');
+
+$fh = $share->write('test.txt');
+fwrite($fh, 'bar');
+fclose($fh);
+```
+
+### Using libsmbclient-php ###
+
+Install [libsmbclient-php](https://github.com/eduardok/libsmbclient-php)
+
+```php
+<?php
+use Icewind\SMB\Server;
+use Icewind\SMB\NativeServer;
+
+require('vendor/autoload.php');
+
+$fileToUpload = __FILE__;
+
+if (Server::NativeAvailable()) {
+ $server = new NativeServer('localhost', 'test', 'test');
+} else {
+ echo 'libsmbclient-php not available, falling back to wrapping smbclient';
+ $server = new Server('localhost', 'test', 'test');
+}
+$share = $server->getShare('test');
+$share->put($fileToUpload, 'example.txt');
+```
diff --git a/apps/files_external/3rdparty/icewind/smb/composer.json b/apps/files_external/3rdparty/icewind/smb/composer.json
new file mode 100644
index 00000000000..92f4280d775
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/composer.json
@@ -0,0 +1,24 @@
+{
+ "name" : "icewind/smb",
+ "description" : "php wrapper for smbclient and libsmbclient-php",
+ "license" : "MIT",
+ "authors" : [
+ {
+ "name" : "Robin Appelman",
+ "email": "icewind@owncloud.com"
+ }
+ ],
+ "require" : {
+ "php": ">=5.3",
+ "icewind/streams": "0.2.x"
+ },
+ "require-dev": {
+ "satooshi/php-coveralls" : "dev-master"
+ },
+ "autoload" : {
+ "psr-4": {
+ "Icewind\\SMB\\": "src/",
+ "Icewind\\SMB\\Test\\": "tests/"
+ }
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Connection.php b/apps/files_external/3rdparty/icewind/smb/src/Connection.php
new file mode 100644
index 00000000000..6191b11ac8e
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Connection.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\AuthenticationException;
+use Icewind\SMB\Exception\ConnectionException;
+use Icewind\SMB\Exception\InvalidHostException;
+
+class Connection extends RawConnection {
+ const DELIMITER = 'smb:';
+
+ /**
+ * send input to smbclient
+ *
+ * @param string $input
+ */
+ public function write($input) {
+ parent::write($input . PHP_EOL);
+ }
+
+ /**
+ * get all unprocessed output from smbclient until the next prompt
+ *
+ * @throws ConnectionException
+ * @return string
+ */
+ public function read() {
+ if (!$this->isValid()) {
+ throw new ConnectionException();
+ }
+ $line = $this->readLine(); //first line is prompt
+ $this->checkConnectionError($line);
+
+ $output = array();
+ $line = $this->readLine();
+ $length = mb_strlen(self::DELIMITER);
+ while (mb_substr($line, 0, $length) !== self::DELIMITER) { //next prompt functions as delimiter
+ $output[] .= $line;
+ $line = $this->readLine();
+ }
+ return $output;
+ }
+
+ /**
+ * check if the first line holds a connection failure
+ *
+ * @param $line
+ * @throws AuthenticationException
+ * @throws InvalidHostException
+ */
+ private function checkConnectionError($line) {
+ $line = rtrim($line, ')');
+ if (substr($line, -23) === ErrorCodes::LogonFailure) {
+ throw new AuthenticationException();
+ }
+ if (substr($line, -26) === ErrorCodes::BadHostName) {
+ throw new InvalidHostException();
+ }
+ if (substr($line, -22) === ErrorCodes::Unsuccessful) {
+ throw new InvalidHostException();
+ }
+ if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
+ throw new InvalidHostException();
+ }
+ }
+
+ public function close($terminate = true) {
+ if (is_resource($this->getInputStream())) {
+ $this->write('close' . PHP_EOL);
+ }
+ parent::close($terminate);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php b/apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php
new file mode 100644
index 00000000000..d9f2507cba9
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/ErrorCodes.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+class ErrorCodes {
+ /**
+ * connection errors
+ */
+ const LogonFailure = 'NT_STATUS_LOGON_FAILURE';
+ const BadHostName = 'NT_STATUS_BAD_NETWORK_NAME';
+ const Unsuccessful = 'NT_STATUS_UNSUCCESSFUL';
+ const ConnectionRefused = 'NT_STATUS_CONNECTION_REFUSED';
+
+ const PathNotFound = 'NT_STATUS_OBJECT_PATH_NOT_FOUND';
+ const NoSuchFile = 'NT_STATUS_NO_SUCH_FILE';
+ const ObjectNotFound = 'NT_STATUS_OBJECT_NAME_NOT_FOUND';
+ const NameCollision = 'NT_STATUS_OBJECT_NAME_COLLISION';
+ const AccessDenied = 'NT_STATUS_ACCESS_DENIED';
+ const DirectoryNotEmpty = 'NT_STATUS_DIRECTORY_NOT_EMPTY';
+ const FileIsADirectory = 'NT_STATUS_FILE_IS_A_DIRECTORY';
+ const NotADirectory = 'NT_STATUS_NOT_A_DIRECTORY';
+ const SharingViolation = 'NT_STATUS_SHARING_VIOLATION';
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php
new file mode 100644
index 00000000000..4b7d22b3540
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/AccessDeniedException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+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
new file mode 100644
index 00000000000..4636b9d1786
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/AlreadyExistsException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+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
new file mode 100644
index 00000000000..ddf5d7e34dc
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/AuthenticationException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+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
new file mode 100644
index 00000000000..310d441bf5c
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class ConnectException extends Exception {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php
new file mode 100644
index 00000000000..21033560fc0
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class ConnectionException extends ConnectException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php
new file mode 100644
index 00000000000..ffebb4c8a51
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ConnectionRefusedException.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class ConnectionRefusedException 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
new file mode 100644
index 00000000000..3307ad57a24
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/Exception.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class Exception extends \Exception {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php
new file mode 100644
index 00000000000..46460eb6936
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/FileInUseException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+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
new file mode 100644
index 00000000000..117d6a438ea
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/ForbiddenException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class ForbiddenException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php
new file mode 100644
index 00000000000..9ae762b6108
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/HostDownException.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class HostDownException extends ConnectException {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php
new file mode 100644
index 00000000000..4b17f1a4de6
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidHostException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class InvalidHostException extends ConnectException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
new file mode 100644
index 00000000000..0dccd8b909e
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidRequestException.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class InvalidRequestException extends Exception {
+ /**
+ * @var string
+ */
+ protected $path;
+
+ /**
+ * @param string $path
+ * @param int $code
+ */
+ public function __construct($path, $code = 0) {
+ parent::__construct('Invalid request for ' . $path, $code);
+ $this->path = $path;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPath() {
+ return $this->path;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php
new file mode 100644
index 00000000000..63b79305ad4
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/InvalidTypeException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class InvalidTypeException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php
new file mode 100644
index 00000000000..03daf36d610
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/NoRouteToHostException.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class NoRouteToHostException 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
new file mode 100644
index 00000000000..789a76bcb9e
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotEmptyException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+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
new file mode 100644
index 00000000000..9ce97cd535b
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/NotFoundException.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class NotFoundException extends InvalidRequestException {}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php
new file mode 100644
index 00000000000..dd57c9b8ccc
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/TimedOutException.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Exception;
+
+class TimedOutException extends ConnectException {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/FileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/FileInfo.php
new file mode 100644
index 00000000000..ef9121a8f57
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/FileInfo.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+class FileInfo implements IFileInfo {
+ /*
+ * Mappings of the DOS mode bits, as returned by smbc_getxattr() when the
+ * attribute name "system.dos_attr.mode" (or "system.dos_attr.*" or
+ * "system.*") is specified.
+ */
+ const MODE_READONLY = 0x01;
+ const MODE_HIDDEN = 0x02;
+ const MODE_SYSTEM = 0x04;
+ const MODE_VOLUME_ID = 0x08;
+ const MODE_DIRECTORY = 0x10;
+ const MODE_ARCHIVE = 0x20;
+ const MODE_NORMAL = 0x80;
+
+ /**
+ * @var string
+ */
+ protected $path;
+
+ /**
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * @var int
+ */
+ protected $size;
+
+ /**
+ * @var int
+ */
+ protected $time;
+
+ /**
+ * @var int
+ */
+ protected $mode;
+
+ /**
+ * @param string $path
+ * @param string $name
+ * @param int $size
+ * @param int $time
+ * @param int $mode
+ */
+ public function __construct($path, $name, $size, $time, $mode) {
+ $this->path = $path;
+ $this->name = $name;
+ $this->size = $size;
+ $this->time = $time;
+ $this->mode = $mode;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPath() {
+ return $this->path;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * @return int
+ */
+ public function getSize() {
+ return $this->size;
+ }
+
+ /**
+ * @return int
+ */
+ public function getMTime() {
+ return $this->time;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isDirectory() {
+ return (bool)($this->mode & self::MODE_DIRECTORY);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isReadOnly() {
+ return (bool)($this->mode & self::MODE_READONLY);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isHidden() {
+ return (bool)($this->mode & self::MODE_HIDDEN);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isSystem() {
+ return (bool)($this->mode & self::MODE_SYSTEM);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isArchived() {
+ return (bool)($this->mode & self::MODE_ARCHIVE);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
new file mode 100644
index 00000000000..16ea8cfbd04
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/IFileInfo.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+interface IFileInfo {
+ /**
+ * @return string
+ */
+ public function getPath();
+
+ /**
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * @return int
+ */
+ public function getSize();
+
+ /**
+ * @return int
+ */
+ public function getMTime();
+
+ /**
+ * @return bool
+ */
+ public function isDirectory();
+
+ /**
+ * @return bool
+ */
+ public function isReadOnly();
+
+ /**
+ * @return bool
+ */
+ public function isHidden();
+
+ /**
+ * @return bool
+ */
+ public function isSystem();
+
+ /**
+ * @return bool
+ */
+ public function isArchived();
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/IShare.php b/apps/files_external/3rdparty/icewind/smb/src/IShare.php
new file mode 100644
index 00000000000..4851e9de053
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/IShare.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+interface IShare {
+ /**
+ * Get the name of the share
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Download a remote file
+ *
+ * @param string $source remove file
+ * @param string $target local file
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function get($source, $target);
+
+ /**
+ * Upload a local file
+ *
+ * @param string $source local file
+ * @param string $target remove file
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function put($source, $target);
+
+ /**
+ * Open a readable stream top a remote file
+ *
+ * @param string $source
+ * @return resource a read only stream with the contents of the remote file
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function read($source);
+
+ /**
+ * Open a writable stream to a remote 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
+ */
+ public function write($target);
+
+ /**
+ * Rename a remote file
+ *
+ * @param string $from
+ * @param string $to
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function rename($from, $to);
+
+ /**
+ * Delete a file on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function del($path);
+
+ /**
+ * List the content of a remote folder
+ *
+ * @param $path
+ * @return \Icewind\SMB\IFileInfo[]
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function dir($path);
+
+ /**
+ * @param string $path
+ * @return \Icewind\SMB\IFileInfo
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ */
+ public function stat($path);
+
+ /**
+ * Create a folder on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function mkdir($path);
+
+ /**
+ * Remove a folder on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function rmdir($path);
+
+ /**
+ * @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
+ */
+ public function setMode($path, $mode);
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php b/apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php
new file mode 100644
index 00000000000..6ef5cf0c5b9
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/NativeFileInfo.php
@@ -0,0 +1,142 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+class NativeFileInfo implements IFileInfo {
+ const MODE_FILE = 0100000;
+
+ /**
+ * @var string
+ */
+ protected $path;
+
+ /**
+ * @var string
+ */
+ protected $name;
+
+ /**
+ * @var \Icewind\SMB\NativeShare
+ */
+ protected $share;
+
+ /**
+ * @var array | null
+ */
+ protected $statCache;
+
+ /**
+ * @var int
+ */
+ protected $modeCache;
+
+ /**
+ * @param \Icewind\SMB\NativeShare $share
+ * @param string $path
+ * @param string $name
+ * @param array $stat
+ */
+ public function __construct($share, $path, $name, $stat = null) {
+ $this->share = $share;
+ $this->path = $path;
+ $this->name = $name;
+ $this->statCache = $stat;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPath() {
+ return $this->path;
+ }
+
+ /**
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * @return array
+ */
+ protected function stat() {
+ if (!$this->statCache) {
+ $this->statCache = $this->share->getStat($this->getPath());
+ }
+ return $this->statCache;
+ }
+
+ /**
+ * @return int
+ */
+ public function getSize() {
+ $stat = $this->stat();
+ return $stat['size'];
+ }
+
+ /**
+ * @return int
+ */
+ public function getMTime() {
+ $stat = $this->stat();
+ return $stat['mtime'];
+ }
+
+ /**
+ * @return bool
+ */
+ public function isDirectory() {
+ $stat = $this->stat();
+ return !($stat['mode'] & self::MODE_FILE);
+ }
+
+ /**
+ * @return int
+ */
+ 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;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isReadOnly() {
+ $mode = $this->getMode();
+ return (bool)($mode & FileInfo::MODE_READONLY);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isHidden() {
+ $mode = $this->getMode();
+ return (bool)($mode & FileInfo::MODE_HIDDEN);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isSystem() {
+ $mode = $this->getMode();
+ return (bool)($mode & FileInfo::MODE_SYSTEM);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isArchived() {
+ $mode = $this->getMode();
+ return (bool)($mode & FileInfo::MODE_ARCHIVE);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeServer.php b/apps/files_external/3rdparty/icewind/smb/src/NativeServer.php
new file mode 100644
index 00000000000..4628e3ec108
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/NativeServer.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+class NativeServer extends Server {
+ /**
+ * @var \Icewind\SMB\NativeState
+ */
+ protected $state;
+
+ /**
+ * @param string $host
+ * @param string $user
+ * @param string $password
+ */
+ public function __construct($host, $user, $password) {
+ parent::__construct($host, $user, $password);
+ $this->state = new NativeState();
+ }
+
+ protected function connect() {
+ $user = $this->getUser();
+ $workgroup = null;
+ if (strpos($user, '/')) {
+ list($workgroup, $user) = explode($user, '/');
+ }
+ $this->state->init($workgroup, $user, $this->getPassword());
+ }
+
+ /**
+ * @return \Icewind\SMB\IShare[]
+ * @throws \Icewind\SMB\Exception\AuthenticationException
+ * @throws \Icewind\SMB\Exception\InvalidHostException
+ */
+ public function listShares() {
+ $this->connect();
+ $shares = array();
+ $dh = $this->state->opendir('smb://' . $this->getHost());
+ while ($share = $this->state->readdir($dh)) {
+ if ($share['type'] === 'file share') {
+ $shares[] = $this->getShare($share['name']);
+ }
+ }
+ $this->state->closedir($dh);
+ return $shares;
+ }
+
+ /**
+ * @param string $name
+ * @return \Icewind\SMB\IShare
+ */
+ public function getShare($name) {
+ return new NativeShare($this, $name);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php
new file mode 100644
index 00000000000..c84e9611667
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/NativeShare.php
@@ -0,0 +1,288 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+class NativeShare implements IShare {
+ /**
+ * @var Server $server
+ */
+ private $server;
+
+ /**
+ * @var string $name
+ */
+ private $name;
+
+ /**
+ * @var \Icewind\SMB\NativeState $state
+ */
+ private $state;
+
+ /**
+ * @param Server $server
+ * @param string $name
+ */
+ public function __construct($server, $name) {
+ $this->server = $server;
+ $this->name = $name;
+ $this->state = new NativeState();
+ }
+
+ /**
+ * @throws \Icewind\SMB\Exception\ConnectionException
+ * @throws \Icewind\SMB\Exception\AuthenticationException
+ * @throws \Icewind\SMB\Exception\InvalidHostException
+ */
+ protected function connect() {
+ if ($this->state and $this->state instanceof NativeShare) {
+ return;
+ }
+
+ $user = $this->server->getUser();
+ if (strpos($user, '/')) {
+ list($workgroup, $user) = explode('/', $user);
+ } elseif (strpos($user, '\\')) {
+ list($workgroup, $user) = explode('\\', $user);
+ } else {
+ $workgroup = null;
+ }
+ $this->state->init($workgroup, $user, $this->server->getPassword());
+ }
+
+ /**
+ * Get the name of the share
+ *
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ private function buildUrl($path) {
+ $url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name);
+ if ($path) {
+ $path = trim($path, '/');
+ $url .= '/';
+ $url .= implode('/', array_map('rawurlencode', explode('/', $path)));
+ }
+ return $url;
+ }
+
+ /**
+ * List the content of a remote folder
+ *
+ * @param string $path
+ * @return \Icewind\SMB\IFileInfo[]
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function dir($path) {
+ $this->connect();
+ $files = array();
+
+ $dh = $this->state->opendir($this->buildUrl($path));
+ while ($file = $this->state->readdir($dh)) {
+ $name = $file['name'];
+ if ($name !== '.' and $name !== '..') {
+ $files [] = new NativeFileInfo($this, $path . '/' . $name, $name);
+ }
+ }
+
+ $this->state->closedir($dh);
+ return $files;
+ }
+
+ /**
+ * @param string $path
+ * @return \Icewind\SMB\IFileInfo[]
+ */
+ public function stat($path) {
+ return new NativeFileInfo($this, $path, basename($path), $this->getStat($path));
+ }
+
+ public function getStat($path) {
+ $this->connect();
+ return $this->state->stat($this->buildUrl($path));
+ }
+
+ /**
+ * Create a folder on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function mkdir($path) {
+ $this->connect();
+ return $this->state->mkdir($this->buildUrl($path));
+ }
+
+ /**
+ * Remove a folder on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function rmdir($path) {
+ $this->connect();
+ return $this->state->rmdir($this->buildUrl($path));
+ }
+
+ /**
+ * Delete a file on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function del($path) {
+ return $this->state->unlink($this->buildUrl($path));
+ }
+
+ /**
+ * Rename a remote file
+ *
+ * @param string $from
+ * @param string $to
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function rename($from, $to) {
+ $this->connect();
+ return $this->state->rename($this->buildUrl($from), $this->buildUrl($to));
+ }
+
+ /**
+ * Upload a local file
+ *
+ * @param string $source local file
+ * @param string $target remove file
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function put($source, $target) {
+ $this->connect();
+ $sourceHandle = fopen($source, 'rb');
+ $targetHandle = $this->state->create($this->buildUrl($target));
+
+ while ($data = fread($sourceHandle, 4096)) {
+ $this->state->write($targetHandle, $data);
+ }
+ $this->state->close($targetHandle);
+ return true;
+ }
+
+ /**
+ * Download a remote file
+ *
+ * @param string $source remove file
+ * @param string $target local file
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function get($source, $target) {
+ $this->connect();
+ $sourceHandle = $this->state->open($this->buildUrl($source), 'r');
+ $targetHandle = fopen($target, 'wb');
+
+ while ($data = $this->state->read($sourceHandle, 4096)) {
+ fwrite($targetHandle, $data);
+ }
+ $this->state->close($sourceHandle);
+ return true;
+ }
+
+ /**
+ * Open a readable stream top a remote file
+ *
+ * @param string $source
+ * @return resource a read only stream with the contents of the remote file
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function read($source) {
+ $this->connect();
+ $handle = $this->state->open($this->buildUrl($source), 'r');
+ return NativeStream::wrap($this->state, $handle, 'r');
+ }
+
+ /**
+ * Open a readable stream top a remote file
+ *
+ * @param string $source
+ * @return resource a read only stream with the contents of the remote file
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function write($source) {
+ $this->connect();
+ $handle = $this->state->create($this->buildUrl($source));
+ return NativeStream::wrap($this->state, $handle, 'w');
+ }
+
+ /**
+ * Get extended attributes for the path
+ *
+ * @param string $path
+ * @param string $attribute attribute to get the info
+ * @return string the attribute value
+ */
+ public function getAttribute($path, $attribute) {
+ $this->connect();
+
+ $result = $this->state->getxattr($this->buildUrl($path), $attribute);
+ return $result;
+ }
+
+ /**
+ * Get extended attributes for the path
+ *
+ * @param string $path
+ * @param string $attribute attribute to get the info
+ * @param mixed $value
+ * @return string the attribute value
+ */
+ public function setAttribute($path, $attribute, $value) {
+ $this->connect();
+
+ if ($attribute === 'system.dos_attr.mode' and is_int($value)) {
+ $value = '0x' . dechex($value);
+ }
+
+ return $this->state->setxattr($this->buildUrl($path), $attribute, $value);
+ }
+
+ /**
+ * @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
+ */
+ public function setMode($path, $mode) {
+ return $this->setAttribute($path, 'system.dos_attr.mode', $mode);
+ }
+
+ public function __destruct() {
+ unset($this->state);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeState.php b/apps/files_external/3rdparty/icewind/smb/src/NativeState.php
new file mode 100644
index 00000000000..e3e344d9e01
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/NativeState.php
@@ -0,0 +1,308 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\AlreadyExistsException;
+use Icewind\SMB\Exception\ConnectionRefusedException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\ForbiddenException;
+use Icewind\SMB\Exception\HostDownException;
+use Icewind\SMB\Exception\InvalidTypeException;
+use Icewind\SMB\Exception\NoRouteToHostException;
+use Icewind\SMB\Exception\NotEmptyException;
+use Icewind\SMB\Exception\NotFoundException;
+use Icewind\SMB\Exception\TimedOutException;
+
+/**
+ * Low level wrapper for libsmbclient-php for error handling
+ */
+class NativeState {
+ /**
+ * @var resource
+ */
+ protected $state;
+
+ protected $handlerSet = false;
+
+ protected $connected = false;
+
+ protected function handleError($path) {
+ $error = smbclient_state_errno($this->state);
+ switch ($error) {
+ // see error.h
+ case 0;
+ return;
+ case 1:
+ case 13:
+ throw new ForbiddenException($path, $error);
+ case 2:
+ throw new NotFoundException($path, $error);
+ case 17:
+ throw new AlreadyExistsException($path, $error);
+ case 20:
+ throw new InvalidTypeException($path, $error);
+ case 21:
+ throw new InvalidTypeException($path, $error);
+ case 39:
+ throw new NotEmptyException($path, $error);
+ case 110:
+ throw new TimedOutException($path, $error);
+ case 111:
+ throw new ConnectionRefusedException($path, $error);
+ case 112:
+ throw new HostDownException($path, $error);
+ case 113:
+ throw new NoRouteToHostException($path, $error);
+ default:
+ $message = 'Unknown error (' . $error . ')';
+ if ($path) {
+ $message .= ' for ' . $path;
+ }
+ throw new Exception($message, $error);
+ }
+ }
+
+ protected function testResult($result, $path) {
+ if ($result === false or $result === null) {
+ $this->handleError($path);
+ }
+ }
+
+ /**
+ * @param string $workGroup
+ * @param string $user
+ * @param string $password
+ * @return bool
+ */
+ public function init($workGroup, $user, $password) {
+ if ($this->connected) {
+ return true;
+ }
+ $this->state = smbclient_state_new();
+ $result = @smbclient_state_init($this->state, $workGroup, $user, $password);
+
+ $this->testResult($result, '');
+ $this->connected = true;
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @return resource
+ */
+ public function opendir($uri) {
+ $result = @smbclient_opendir($this->state, $uri);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param resource $dir
+ * @return array
+ */
+ public function readdir($dir) {
+ $result = @smbclient_readdir($this->state, $dir);
+
+ $this->testResult($result, $dir);
+ return $result;
+ }
+
+ /**
+ * @param $dir
+ * @return bool
+ */
+ public function closedir($dir) {
+ $result = smbclient_closedir($this->state, $dir);
+
+ $this->testResult($result, $dir);
+ return $result;
+ }
+
+ /**
+ * @param string $old
+ * @param string $new
+ * @return bool
+ */
+ public function rename($old, $new) {
+ $result = @smbclient_rename($this->state, $old, $this->state, $new);
+
+ $this->testResult($result, $new);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @return bool
+ */
+ public function unlink($uri) {
+ $result = @smbclient_unlink($this->state, $uri);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @param int $mask
+ * @return bool
+ */
+ public function mkdir($uri, $mask = 0777) {
+ $result = @smbclient_mkdir($this->state, $uri, $mask);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @return bool
+ */
+ public function rmdir($uri) {
+ $result = @smbclient_rmdir($this->state, $uri);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @return array
+ */
+ public function stat($uri) {
+ $result = @smbclient_stat($this->state, $uri);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param resource $file
+ * @return array
+ */
+ public function fstat($file) {
+ $result = @smbclient_fstat($this->state, $file);
+
+ $this->testResult($result, $file);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @param string $mode
+ * @param int $mask
+ * @return resource
+ */
+ public function open($uri, $mode, $mask = 0666) {
+ $result = @smbclient_open($this->state, $uri, $mode, $mask);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @param int $mask
+ * @return resource
+ */
+ public function create($uri, $mask = 0666) {
+ $result = @smbclient_creat($this->state, $uri, $mask);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param resource $file
+ * @param int $bytes
+ * @return string
+ */
+ public function read($file, $bytes) {
+ $result = @smbclient_read($this->state, $file, $bytes);
+
+ $this->testResult($result, $file);
+ return $result;
+ }
+
+ /**
+ * @param resource $file
+ * @param string $data
+ * @param int $length
+ * @return int
+ */
+ public function write($file, $data, $length = null) {
+ $result = @smbclient_write($this->state, $file, $data, $length);
+
+ $this->testResult($result, $file);
+ return $result;
+ }
+
+ /**
+ * @param resource $file
+ * @param int $offset
+ * @param int $whence SEEK_SET | SEEK_CUR | SEEK_END
+ * @return int | bool new file offset as measured from the start of the file on success, false on failure.
+ */
+ public function lseek($file, $offset, $whence = SEEK_SET) {
+ $result = @smbclient_lseek($this->state, $file, $offset, $whence);
+
+ $this->testResult($result, $file);
+ return $result;
+ }
+
+ /**
+ * @param resource $file
+ * @param int $size
+ * @return bool
+ */
+ public function ftruncate($file, $size) {
+ $result = @smbclient_ftruncate($this->state, $file, $size);
+
+ $this->testResult($result, $file);
+ return $result;
+ }
+
+ public function close($file) {
+ $result = @smbclient_close($this->state, $file);
+
+ $this->testResult($result, $file);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @param string $key
+ * @return string
+ */
+ public function getxattr($uri, $key) {
+ $result = @smbclient_getxattr($this->state, $uri, $key);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ /**
+ * @param string $uri
+ * @param string $key
+ * @param string $value
+ * @param int $flags
+ * @return mixed
+ */
+ public function setxattr($uri, $key, $value, $flags = 0) {
+ $result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags);
+
+ $this->testResult($result, $uri);
+ return $result;
+ }
+
+ public function __destruct() {
+ if ($this->connected) {
+ smbclient_state_free($this->state);
+ }
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NativeStream.php b/apps/files_external/3rdparty/icewind/smb/src/NativeStream.php
new file mode 100644
index 00000000000..07bd2f1e797
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/NativeStream.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\InvalidRequestException;
+use Icewind\Streams\File;
+
+class NativeStream implements File {
+ /**
+ * @var resource
+ */
+ public $context;
+
+ /**
+ * @var \Icewind\SMB\NativeState
+ */
+ private $state;
+
+ /**
+ * @var resource
+ */
+ private $handle;
+
+ /**
+ * @var bool
+ */
+ private $eof = false;
+
+ /**
+ * Wrap a stream from libsmbclient-php into a regular php stream
+ *
+ * @param \Icewind\SMB\NativeState $state
+ * @param resource $smbStream
+ * @param string $mode
+ * @return resource
+ */
+ public static function wrap($state, $smbStream, $mode) {
+ stream_wrapper_register('nativesmb', '\Icewind\SMB\NativeStream');
+ $context = stream_context_create(array(
+ 'nativesmb' => array(
+ 'state' => $state,
+ 'handle' => $smbStream
+ )
+ ));
+ $fh = fopen('nativesmb://', $mode, false, $context);
+ stream_wrapper_unregister('nativesmb');
+ return $fh;
+ }
+
+ public function stream_close() {
+ return $this->state->close($this->handle);
+ }
+
+ public function stream_eof() {
+ return $this->eof;
+ }
+
+ public function stream_flush() {
+ }
+
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ $context = stream_context_get_options($this->context);
+ $this->state = $context['nativesmb']['state'];
+ $this->handle = $context['nativesmb']['handle'];
+ return true;
+ }
+
+ public function stream_read($count) {
+ $result = $this->state->read($this->handle, $count);
+ if (strlen($result) < $count) {
+ $this->eof = true;
+ }
+ return $result;
+ }
+
+ public function stream_seek($offset, $whence = SEEK_SET) {
+ $this->eof = false;
+ try {
+ return $this->state->lseek($this->handle, $offset, $whence) !== false;
+ } catch (InvalidRequestException $e) {
+ return false;
+ }
+ }
+
+ public function stream_stat() {
+ return $this->state->fstat($this->handle);
+ }
+
+ public function stream_tell() {
+ return $this->state->lseek($this->handle, 0, SEEK_CUR);
+ }
+
+ public function stream_write($data) {
+ return $this->state->write($this->handle, $data);
+ }
+
+ public function stream_truncate($size) {
+ return $this->state->ftruncate($this->handle, $size);
+ }
+
+ public function stream_set_option($option, $arg1, $arg2) {
+ return false;
+ }
+
+ public function stream_lock($operation) {
+ return false;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Parser.php b/apps/files_external/3rdparty/icewind/smb/src/Parser.php
new file mode 100644
index 00000000000..645678d9855
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Parser.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\AccessDeniedException;
+use Icewind\SMB\Exception\AlreadyExistsException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\FileInUseException;
+use Icewind\SMB\Exception\InvalidTypeException;
+use Icewind\SMB\Exception\NotEmptyException;
+use Icewind\SMB\Exception\NotFoundException;
+
+class Parser {
+ /**
+ * @var string
+ */
+ protected $timeZone;
+
+ /**
+ * @param string $timeZone
+ */
+ public function __construct($timeZone) {
+ $this->timeZone = $timeZone;
+ }
+
+ public function checkForError($output, $path) {
+ if (count($output) === 0) {
+ return true;
+ } else {
+ if (strpos($output[0], 'does not exist')) {
+ throw new NotFoundException($path);
+ }
+ $parts = explode(' ', $output[0]);
+ $error = false;
+ foreach ($parts as $part) {
+ if (substr($part, 0, 9) === 'NT_STATUS') {
+ $error = $part;
+ }
+ }
+ switch ($error) {
+ case ErrorCodes::PathNotFound:
+ case ErrorCodes::ObjectNotFound:
+ case ErrorCodes::NoSuchFile:
+ throw new NotFoundException($path);
+ case ErrorCodes::NameCollision:
+ throw new AlreadyExistsException($path);
+ case ErrorCodes::AccessDenied:
+ throw new AccessDeniedException($path);
+ case ErrorCodes::DirectoryNotEmpty:
+ throw new NotEmptyException($path);
+ case ErrorCodes::FileIsADirectory:
+ case ErrorCodes::NotADirectory:
+ throw new InvalidTypeException($path);
+ case ErrorCodes::SharingViolation:
+ throw new FileInUseException($path);
+ default:
+ $message = 'Unknown error (' . $error . ')';
+ if ($path) {
+ $message .= ' for ' . $path;
+ }
+ throw new Exception($message);
+ }
+ }
+ }
+
+ public function parseMode($mode) {
+ $result = 0;
+ $modeStrings = array(
+ 'R' => FileInfo::MODE_READONLY,
+ 'H' => FileInfo::MODE_HIDDEN,
+ 'S' => FileInfo::MODE_SYSTEM,
+ 'D' => FileInfo::MODE_DIRECTORY,
+ 'A' => FileInfo::MODE_ARCHIVE,
+ 'N' => FileInfo::MODE_NORMAL
+ );
+ foreach ($modeStrings as $char => $val) {
+ if (strpos($mode, $char) !== false) {
+ $result |= $val;
+ }
+ }
+ return $result;
+ }
+
+ public function parseStat($output) {
+ $mtime = 0;
+ $mode = 0;
+ $size = 0;
+ foreach ($output as $line) {
+ list($name, $value) = explode(':', $line, 2);
+ $value = trim($value);
+ if ($name === 'write_time') {
+ $mtime = strtotime($value);
+ } else if ($name === 'attributes') {
+ $mode = hexdec(substr($value, 1, -1));
+ } else if ($name === 'stream') {
+ list(, $size,) = explode(' ', $value);
+ $size = intval($size);
+ }
+ }
+ return array(
+ 'mtime' => $mtime,
+ 'mode' => $mode,
+ 'size' => $size
+ );
+ }
+
+ public function parseDir($output, $basePath) {
+ //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();
+ 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->timeZone);
+ $content[] = new FileInfo($basePath . '/' . $name, $name, $size, $time, $mode);
+ }
+ }
+ }
+ return $content;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/RawConnection.php b/apps/files_external/3rdparty/icewind/smb/src/RawConnection.php
new file mode 100644
index 00000000000..926ce3714cf
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/RawConnection.php
@@ -0,0 +1,165 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\ConnectionException;
+
+class RawConnection {
+ /**
+ * @var string
+ */
+ private $command;
+
+ /**
+ * @var string[]
+ */
+ private $env;
+
+ /**
+ * @var resource[] $pipes
+ *
+ * $pipes[0] holds STDIN for smbclient
+ * $pipes[1] holds STDOUT for smbclient
+ */
+ private $pipes;
+
+ /**
+ * @var resource $process
+ */
+ private $process;
+
+ public function __construct($command, $env = array()) {
+ $this->command = $command;
+ $this->env = $env;
+ $this->connect();
+ }
+
+ private function connect() {
+ $descriptorSpec = array(
+ 0 => array('pipe', 'r'), // child reads from stdin
+ 1 => array('pipe', 'w'), // child writes to stdout
+ 2 => array('pipe', 'w'), // child writes to stderr
+ 3 => array('pipe', 'r'), // child reads from fd#3
+ 4 => array('pipe', 'r'), // child reads from fd#4
+ 5 => array('pipe', 'w') // child writes to fd#5
+ );
+ setlocale(LC_ALL, Server::LOCALE);
+ $env = array_merge($this->env, array(
+ 'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!!
+ 'LC_ALL' => Server::LOCALE,
+ 'LANG' => Server::LOCALE,
+ 'COLUMNS' => 8192 // prevent smbclient from line-wrapping it's output
+ ));
+ $this->process = proc_open($this->command, $descriptorSpec, $this->pipes, '/', $env);
+ if (!$this->isValid()) {
+ throw new ConnectionException();
+ }
+ }
+
+ /**
+ * check if the connection is still active
+ *
+ * @return bool
+ */
+ public function isValid() {
+ if (is_resource($this->process)) {
+ $status = proc_get_status($this->process);
+ return $status['running'];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * send input to the process
+ *
+ * @param string $input
+ */
+ public function write($input) {
+ fwrite($this->getInputStream(), $input);
+ fflush($this->getInputStream());
+ }
+
+ /**
+ * read a line of output
+ *
+ * @return string
+ */
+ public function readLine() {
+ return stream_get_line($this->getOutputStream(), 4086, "\n");
+ }
+
+ /**
+ * get all output until the process closes
+ *
+ * @return array
+ */
+ public function readAll() {
+ $output = array();
+ while ($line = $this->readLine()) {
+ $output[] = $line;
+ }
+ return $output;
+ }
+
+ public function getInputStream() {
+ return $this->pipes[0];
+ }
+
+ public function getOutputStream() {
+ return $this->pipes[1];
+ }
+
+ public function getErrorStream() {
+ return $this->pipes[2];
+ }
+
+ public function getAuthStream() {
+ return $this->pipes[3];
+ }
+
+ public function getFileInputStream() {
+ return $this->pipes[4];
+ }
+
+ public function getFileOutputStream() {
+ return $this->pipes[5];
+ }
+
+ public function writeAuthentication($user, $password) {
+ $auth = ($password === false)
+ ? "username=$user"
+ : "username=$user\npassword=$password";
+
+ if (fwrite($this->getAuthStream(), $auth) === false) {
+ fclose($this->getAuthStream());
+ return false;
+ }
+ fclose($this->getAuthStream());
+ return true;
+ }
+
+ public function close($terminate = true) {
+ if (!is_resource($this->process)) {
+ return;
+ }
+ if ($terminate) {
+ proc_terminate($this->process);
+ }
+ proc_close($this->process);
+ }
+
+ public function reconnect() {
+ $this->close();
+ $this->connect();
+ }
+
+ public function __destruct() {
+ $this->close();
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Server.php b/apps/files_external/3rdparty/icewind/smb/src/Server.php
new file mode 100644
index 00000000000..f7227d4baef
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Server.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\AuthenticationException;
+use Icewind\SMB\Exception\InvalidHostException;
+
+class Server {
+ const CLIENT = 'smbclient';
+ const LOCALE = 'en_US.UTF-8';
+
+ /**
+ * @var string $host
+ */
+ protected $host;
+
+ /**
+ * @var string $user
+ */
+ protected $user;
+
+ /**
+ * @var string $password
+ */
+ protected $password;
+
+ /**
+ * Check if the smbclient php extension is available
+ *
+ * @return bool
+ */
+ public static function NativeAvailable() {
+ return function_exists('smbclient_state_new');
+ }
+
+ /**
+ * @param string $host
+ * @param string $user
+ * @param string $password
+ */
+ public function __construct($host, $user, $password) {
+ $this->host = $host;
+ $this->user = $user;
+ $this->password = $password;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAuthString() {
+ return $this->user . '%' . $this->password;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUser() {
+ return $this->user;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPassword() {
+ return $this->password;
+ }
+
+ /**
+ * return string
+ */
+ public function getHost() {
+ return $this->host;
+ }
+
+ /**
+ * @return \Icewind\SMB\IShare[]
+ *
+ * @throws \Icewind\SMB\Exception\AuthenticationException
+ * @throws \Icewind\SMB\Exception\InvalidHostException
+ */
+ public function listShares() {
+ $command = Server::CLIENT . ' --authentication-file=/proc/self/fd/3' .
+ ' -gL ' . escapeshellarg($this->getHost());
+ $connection = new RawConnection($command);
+ $connection->writeAuthentication($this->getUser(), $this->getPassword());
+ $output = $connection->readAll();
+
+ $line = $output[0];
+
+ $line = rtrim($line, ')');
+ if (substr($line, -23) === ErrorCodes::LogonFailure) {
+ throw new AuthenticationException();
+ }
+ if (substr($line, -26) === ErrorCodes::BadHostName) {
+ throw new InvalidHostException();
+ }
+ if (substr($line, -22) === ErrorCodes::Unsuccessful) {
+ throw new InvalidHostException();
+ }
+ if (substr($line, -28) === ErrorCodes::ConnectionRefused) {
+ throw new InvalidHostException();
+ }
+
+ $shareNames = array();
+ foreach ($output as $line) {
+ if (strpos($line, '|')) {
+ list($type, $name, $description) = explode('|', $line);
+ if (strtolower($type) === 'disk') {
+ $shareNames[$name] = $description;
+ }
+ }
+ }
+
+ $shares = array();
+ foreach ($shareNames as $name => $description) {
+ $shares[] = $this->getShare($name);
+ }
+ return $shares;
+ }
+
+ /**
+ * @param string $name
+ * @return \Icewind\SMB\IShare
+ */
+ public function getShare($name) {
+ return new Share($this, $name);
+ }
+
+ /**
+ * @return string
+ */
+ public function getTimeZone() {
+ $command = 'net time zone -S ' . escapeshellarg($this->getHost());
+ return exec($command);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Share.php b/apps/files_external/3rdparty/icewind/smb/src/Share.php
new file mode 100644
index 00000000000..5c48b1702fa
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Share.php
@@ -0,0 +1,394 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB;
+
+use Icewind\SMB\Exception\AccessDeniedException;
+use Icewind\SMB\Exception\AlreadyExistsException;
+use Icewind\SMB\Exception\ConnectionException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\FileInUseException;
+use Icewind\SMB\Exception\InvalidTypeException;
+use Icewind\SMB\Exception\NotEmptyException;
+use Icewind\SMB\Exception\NotFoundException;
+use Icewind\Streams\CallbackWrapper;
+
+class Share implements IShare {
+ /**
+ * @var Server $server
+ */
+ private $server;
+
+ /**
+ * @var string $name
+ */
+ private $name;
+
+ /**
+ * @var Connection $connection
+ */
+ public $connection;
+
+ /**
+ * @var \Icewind\SMB\Parser
+ */
+ protected $parser;
+
+ private $serverTimezone;
+
+ /**
+ * @param Server $server
+ * @param string $name
+ */
+ public function __construct($server, $name) {
+ $this->server = $server;
+ $this->name = $name;
+ $this->parser = new Parser($this->server->getTimeZone());
+ }
+
+ /**
+ * @throws \Icewind\SMB\Exception\ConnectionException
+ * @throws \Icewind\SMB\Exception\AuthenticationException
+ * @throws \Icewind\SMB\Exception\InvalidHostException
+ */
+ protected function connect() {
+ if ($this->connection and $this->connection->isValid()) {
+ return;
+ }
+ $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s',
+ Server::CLIENT,
+ $this->server->getHost(),
+ $this->name
+ );
+ $this->connection = new Connection($command);
+ $this->connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+ if (!$this->connection->isValid()) {
+ throw new ConnectionException();
+ }
+ }
+
+ protected function reconnect() {
+ $this->connection->reconnect();
+ $this->connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+ if (!$this->connection->isValid()) {
+ throw new ConnectionException();
+ }
+ }
+
+ /**
+ * Get the name of the share
+ *
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ protected function simpleCommand($command, $path) {
+ $path = $this->escapePath($path);
+ $cmd = $command . ' ' . $path;
+ $output = $this->execute($cmd);
+ return $this->parseOutput($output, $path);
+ }
+
+ /**
+ * List the content of a remote folder
+ *
+ * @param $path
+ * @return \Icewind\SMB\IFileInfo[]
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function dir($path) {
+ $escapedPath = $this->escapePath($path);
+ $output = $this->execute('cd ' . $escapedPath);
+ //check output for errors
+ $this->parseOutput($output, $path);
+ $output = $this->execute('dir');
+ $this->execute('cd /');
+
+ return $this->parser->parseDir($output, $path);
+ }
+
+ /**
+ * @param string $path
+ * @return \Icewind\SMB\IFileInfo[]
+ */
+ public function stat($path) {
+ $escapedPath = $this->escapePath($path);
+ $output = $this->execute('allinfo ' . $escapedPath);
+ if (count($output) < 3) {
+ $this->parseOutput($output, $path);
+ }
+ $stat = $this->parser->parseStat($output);
+ return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode']);
+ }
+
+ /**
+ * Create a folder on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function mkdir($path) {
+ return $this->simpleCommand('mkdir', $path);
+ }
+
+ /**
+ * Remove a folder on the share
+ *
+ * @param string $path
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function rmdir($path) {
+ return $this->simpleCommand('rmdir', $path);
+ }
+
+ /**
+ * Delete a file on the share
+ *
+ * @param string $path
+ * @param bool $secondTry
+ * @return bool
+ * @throws InvalidTypeException
+ * @throws NotFoundException
+ * @throws \Exception
+ */
+ public function del($path, $secondTry = false) {
+ //del return a file not found error when trying to delete a folder
+ //we catch it so we can check if $path doesn't exist or is of invalid type
+ try {
+ return $this->simpleCommand('del', $path);
+ } catch (NotFoundException $e) {
+ //no need to do anything with the result, we just check if this throws the not found error
+ try {
+ $this->simpleCommand('ls', $path);
+ } catch (NotFoundException $e2) {
+ throw $e;
+ } catch (\Exception $e2) {
+ throw new InvalidTypeException($path);
+ }
+ throw $e;
+ } catch (FileInUseException $e) {
+ if ($secondTry) {
+ throw $e;
+ }
+ $this->reconnect();
+ return $this->del($path, true);
+ }
+ }
+
+ /**
+ * Rename a remote file
+ *
+ * @param string $from
+ * @param string $to
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function rename($from, $to) {
+ $path1 = $this->escapePath($from);
+ $path2 = $this->escapePath($to);
+ $cmd = 'rename ' . $path1 . ' ' . $path2;
+ $output = $this->execute($cmd);
+ return $this->parseOutput($output, $to);
+ }
+
+ /**
+ * Upload a local file
+ *
+ * @param string $source local file
+ * @param string $target remove file
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function put($source, $target) {
+ $path1 = $this->escapeLocalPath($source); //first path is local, needs different escaping
+ $path2 = $this->escapePath($target);
+ $output = $this->execute('put ' . $path1 . ' ' . $path2);
+ return $this->parseOutput($output, $target);
+ }
+
+ /**
+ * Download a remote file
+ *
+ * @param string $source remove file
+ * @param string $target local file
+ * @return bool
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function get($source, $target) {
+ $path1 = $this->escapePath($source);
+ $path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping
+ $output = $this->execute('get ' . $path1 . ' ' . $path2);
+ return $this->parseOutput($output, $source);
+ }
+
+ /**
+ * Open a readable stream to a remote file
+ *
+ * @param string $source
+ * @return resource a read only stream with the contents of the remote file
+ *
+ * @throws \Icewind\SMB\Exception\NotFoundException
+ * @throws \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function read($source) {
+ $source = $this->escapePath($source);
+ // close the single quote, open a double quote where we put the single quote...
+ $source = str_replace('\'', '\'"\'"\'', $source);
+ // since returned stream is closed by the caller we need to create a new instance
+ // since we can't re-use the same file descriptor over multiple calls
+ $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s -c \'get %s /proc/self/fd/5\'',
+ Server::CLIENT,
+ $this->server->getHost(),
+ $this->name,
+ $source
+ );
+ $connection = new Connection($command);
+ $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+ $fh = $connection->getFileOutputStream();
+ stream_context_set_option($fh, 'file', 'connection', $connection);
+ return $fh;
+ }
+
+ /**
+ * Open a writable stream to a remote 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
+ */
+ public function write($target) {
+ $target = $this->escapePath($target);
+ // close the single quote, open a double quote where we put the single quote...
+ $target = str_replace('\'', '\'"\'"\'', $target);
+ // since returned stream is closed by the caller we need to create a new instance
+ // since we can't re-use the same file descriptor over multiple calls
+ $command = sprintf('%s --authentication-file=/proc/self/fd/3 //%s/%s -c \'put /proc/self/fd/4 %s\'',
+ Server::CLIENT,
+ $this->server->getHost(),
+ $this->name,
+ $target
+ );
+ $connection = new RawConnection($command);
+ $connection->writeAuthentication($this->server->getUser(), $this->server->getPassword());
+ $fh = $connection->getFileInputStream();
+
+ // use a close callback to ensure the upload is finished before continuing
+ // this also serves as a way to keep the connection in scope
+ return CallbackWrapper::wrap($fh, null, null, function () use ($connection) {
+ $connection->close(false); // dont terminate, give the upload some time
+ });
+ }
+
+ /**
+ * @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
+ */
+ public function setMode($path, $mode) {
+ $modeString = '';
+ $modeMap = array(
+ FileInfo::MODE_READONLY => 'r',
+ FileInfo::MODE_HIDDEN => 'h',
+ FileInfo::MODE_ARCHIVE => 'a',
+ FileInfo::MODE_SYSTEM => 's'
+ );
+ foreach ($modeMap as $modeByte => $string) {
+ if ($mode & $modeByte) {
+ $modeString .= $string;
+ }
+ }
+ $path = $this->escapePath($path);
+
+ // first reset the mode to normal
+ $cmd = 'setmode ' . $path . ' -rsha';
+ $output = $this->execute($cmd);
+ $this->parseOutput($output, $path);
+
+ // then set the modes we want
+ $cmd = 'setmode ' . $path . ' ' . $modeString;
+ $output = $this->execute($cmd);
+ return $this->parseOutput($output, $path);
+ }
+
+ /**
+ * @param string $command
+ * @return array
+ */
+ protected function execute($command) {
+ $this->connect();
+ $this->connection->write($command . PHP_EOL);
+ $output = $this->connection->read();
+ return $output;
+ }
+
+ /**
+ * check output for errors
+ *
+ * @param string[] $lines
+ * @param string $path
+ *
+ * @throws NotFoundException
+ * @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
+ */
+ protected function parseOutput($lines, $path = '') {
+ $this->parser->checkForError($lines, $path);
+ }
+
+ /**
+ * @param string $string
+ * @return string
+ */
+ protected function escape($string) {
+ return escapeshellarg($string);
+ }
+
+ /**
+ * @param string $path
+ * @return string
+ */
+ protected function escapePath($path) {
+ $path = str_replace('/', '\\', $path);
+ $path = str_replace('"', '^"', $path);
+ return '"' . $path . '"';
+ }
+
+ /**
+ * @param string $path
+ * @return string
+ */
+ protected function escapeLocalPath($path) {
+ $path = str_replace('"', '\"', $path);
+ return '"' . $path . '"';
+ }
+
+ public function __destruct() {
+ unset($this->connection);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php b/apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php
new file mode 100644
index 00000000000..117fff1ca19
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/AbstractShare.php
@@ -0,0 +1,534 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Test;
+
+use Icewind\SMB\FileInfo;
+
+abstract class AbstractShare extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var \Icewind\SMB\Server $server
+ */
+ protected $server;
+
+ /**
+ * @var \Icewind\SMB\IShare $share
+ */
+ protected $share;
+
+ /**
+ * @var string $root
+ */
+ protected $root;
+
+ protected $config;
+
+ public function tearDown() {
+ try {
+ if ($this->share) {
+ $this->cleanDir($this->root);
+ }
+ unset($this->share);
+ } catch (\Exception $e) {
+ unset($this->share);
+ throw $e;
+ }
+ }
+
+ public function nameProvider() {
+ // / ? < > \ : * | " are illegal characters in path on windows
+ return array(
+ array('simple'),
+ array('with spaces_and-underscores'),
+ array("single'quote'"),
+ array('日本語'),
+ array('url %2F +encode'),
+ array('a somewhat longer filename than the other with more charaters as the all the other filenames'),
+ array('$as#d€££Ö€ßœĚęĘĞĜΣΥΦΩΫ')
+ );
+ }
+
+ public function fileDataProvider() {
+ return array(
+ array('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua'),
+ array('Mixed language, 日本語 が わからか and Various _/* characters \\|” €')
+ );
+ }
+
+ public function nameAndDataProvider() {
+ $names = $this->nameProvider();
+ $data = $this->fileDataProvider();
+ $result = array();
+ foreach ($names as $name) {
+ foreach ($data as $text) {
+ $result[] = array($name[0], $text[0]);
+ }
+ }
+ return $result;
+ }
+
+ public function cleanDir($dir) {
+ $content = $this->share->dir($dir);
+ foreach ($content as $metadata) {
+ if ($metadata->isDirectory()) {
+ $this->cleanDir($metadata->getPath());
+ } else {
+ $this->share->del($metadata->getPath());
+ }
+ }
+ $this->share->rmdir($dir);
+ }
+
+ private function getTextFile($text = '') {
+ if (!$text) {
+ $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua';
+ }
+ $file = tempnam('/tmp', 'smb_test_');
+ file_put_contents($file, $text);
+ return $file;
+ }
+
+ public function testListShares() {
+ $shares = $this->server->listShares();
+ foreach ($shares as $share) {
+ if ($share->getName() === $this->config->share) {
+ return;
+ }
+ }
+ $this->fail('Share "' . $this->config->share . '" not found');
+ }
+
+ public function testRootStartsEmpty() {
+ $this->assertEquals(array(), $this->share->dir($this->root));
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testMkdir($name) {
+ $this->share->mkdir($this->root . '/' . $name);
+ $dirs = $this->share->dir($this->root);
+ $this->assertCount(1, $dirs);
+ $this->assertEquals($name, $dirs[0]->getName());
+ $this->assertTrue($dirs[0]->isDirectory());
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testRenameDirectory($name) {
+ $this->share->mkdir($this->root . '/' . $name);
+ $this->share->rename($this->root . '/' . $name, $this->root . '/' . $name . '_rename');
+ $dirs = $this->share->dir($this->root);
+ $this->assertEquals(1, count($dirs));
+ $this->assertEquals($name . '_rename', $dirs[0]->getName());
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testRmdir($name) {
+ $this->share->mkdir($this->root . '/' . $name);
+ $this->share->rmdir($this->root . '/' . $name);
+ $this->assertCount(0, $this->share->dir($this->root));
+ }
+
+ /**
+ * @dataProvider nameAndDataProvider
+ */
+ public function testPut($name, $text) {
+ $tmpFile = $this->getTextFile($text);
+ $size = filesize($tmpFile);
+
+ $this->share->put($tmpFile, $this->root . '/' . $name);
+ unlink($tmpFile);
+
+ $files = $this->share->dir($this->root);
+ $this->assertCount(1, $files);
+ $this->assertEquals($name, $files[0]->getName());
+ $this->assertEquals($size, $files[0]->getSize());
+ $this->assertFalse($files[0]->isDirectory());
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testRenameFile($name) {
+ $tmpFile = $this->getTextFile();
+
+ $this->share->put($tmpFile, $this->root . '/' . $name);
+ unlink($tmpFile);
+
+ $this->share->rename($this->root . '/' . $name, $this->root . '/' . $name . '_renamed');
+
+ $files = $this->share->dir($this->root);
+ $this->assertEquals(1, count($files));
+ $this->assertEquals($name . '_renamed', $files[0]->getName());
+ }
+
+ /**
+ * @dataProvider nameAndDataProvider
+ */
+ public function testGet($name, $text) {
+ $tmpFile = $this->getTextFile($text);
+
+ $this->share->put($tmpFile, $this->root . '/' . $name);
+ unlink($tmpFile);
+
+ $targetFile = tempnam('/tmp', 'smb_test_');
+ $this->share->get($this->root . '/' . $name, $targetFile);
+
+ $this->assertEquals($text, file_get_contents($targetFile));
+ unlink($targetFile);
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testDel($name) {
+ $tmpFile = $this->getTextFile();
+
+ $this->share->put($tmpFile, $this->root . '/' . $name);
+ unlink($tmpFile);
+
+ $this->share->del($this->root . '/' . $name);
+ $this->assertCount(0, $this->share->dir($this->root));
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testCreateFolderInNonExistingFolder() {
+ $this->share->mkdir($this->root . '/foo/bar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testRemoveFolderInNonExistingFolder() {
+ $this->share->rmdir($this->root . '/foo/bar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testRemoveNonExistingFolder() {
+ $this->share->rmdir($this->root . '/foo');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\AlreadyExistsException
+ */
+ public function testCreateExistingFolder() {
+ $this->share->mkdir($this->root . '/bar');
+ $this->share->mkdir($this->root . '/bar');
+ $this->share->rmdir($this->root . '/bar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function testCreateFileExistingFolder() {
+ $this->share->mkdir($this->root . '/bar');
+ $this->share->put($this->getTextFile(), $this->root . '/bar');
+ $this->share->rmdir($this->root . '/bar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testCreateFileInNonExistingFolder() {
+ $this->share->put($this->getTextFile(), $this->root . '/foo/bar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testTestRemoveNonExistingFile() {
+ $this->share->del($this->root . '/foo');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testDownloadNonExistingFile() {
+ $this->share->get($this->root . '/foo', '/dev/null');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function testDownloadFolder() {
+ $this->share->mkdir($this->root . '/foobar');
+ $this->share->get($this->root . '/foobar', '/dev/null');
+ $this->share->rmdir($this->root . '/foobar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function testDelFolder() {
+ $this->share->mkdir($this->root . '/foobar');
+ $this->share->del($this->root . '/foobar');
+ $this->share->rmdir($this->root . '/foobar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\InvalidTypeException
+ */
+ public function testRmdirFile() {
+ $this->share->put($this->getTextFile(), $this->root . '/foobar');
+ $this->share->rmdir($this->root . '/foobar');
+ $this->share->del($this->root . '/foobar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotEmptyException
+ */
+ public function testRmdirNotEmpty() {
+ $this->share->mkdir($this->root . '/foobar');
+ $this->share->put($this->getTextFile(), $this->root . '/foobar/asd');
+ $this->share->rmdir($this->root . '/foobar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testDirNonExisting() {
+ $this->share->dir('/foobar/asd');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testRmDirNonExisting() {
+ $this->share->rmdir('/foobar/asd');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testRenameNonExisting() {
+ $this->share->rename('/foobar/asd', '/foobar/bar');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testRenameTargetNonExisting() {
+ $txt = $this->getTextFile();
+ $this->share->put($txt, $this->root . '/foo.txt');
+ unlink($txt);
+ $this->share->rename($this->root . '/foo.txt', $this->root . '/bar/foo.txt');
+ }
+
+ public function testModifiedDate() {
+ $now = time();
+ $this->share->put($this->getTextFile(), $this->root . '/foo.txt');
+ $dir = $this->share->dir($this->root);
+ $mtime = $dir[0]->getMTime();
+ $this->assertTrue(abs($now - $mtime) <= 1, 'Modified time differs by ' . abs($now - $mtime) . ' seconds');
+ $this->share->del($this->root . '/foo.txt');
+ }
+
+ /**
+ * @dataProvider nameAndDataProvider
+ */
+ public function testReadStream($name, $text) {
+ $sourceFile = $this->getTextFile($text);
+ $this->share->put($sourceFile, $this->root . '/' . $name);
+ $fh = $this->share->read($this->root . '/' . $name);
+ $content = stream_get_contents($fh);
+ fclose($fh);
+ $this->share->del($this->root . '/' . $name);
+
+ $this->assertEquals(file_get_contents($sourceFile), $content);
+ }
+
+ /**
+ * @dataProvider nameAndDataProvider
+ */
+ public function testWriteStream($name, $text) {
+ $fh = $this->share->write($this->root . '/' . $name);
+ fwrite($fh, $text);
+ fclose($fh);
+
+ $tmpFile1 = tempnam('/tmp', 'smb_test_');
+ $this->share->get($this->root . '/' . $name, $tmpFile1);
+ $this->assertEquals($text, file_get_contents($tmpFile1));
+ $this->share->del($this->root . '/' . $name);
+ unlink($tmpFile1);
+ }
+
+ public function testDir() {
+ $txtFile = $this->getTextFile();
+
+ $this->share->mkdir($this->root . '/dir');
+ $this->share->put($txtFile, $this->root . '/file.txt');
+ unlink($txtFile);
+
+ $dir = $this->share->dir($this->root);
+ if ($dir[0]->getName() === 'dir') {
+ $dirEntry = $dir[0];
+ } else {
+ $dirEntry = $dir[1];
+ }
+ $this->assertTrue($dirEntry->isDirectory());
+ $this->assertFalse($dirEntry->isReadOnly());
+ $this->assertFalse($dirEntry->isReadOnly());
+
+ if ($dir[0]->getName() === 'file.txt') {
+ $fileEntry = $dir[0];
+ } else {
+ $fileEntry = $dir[1];
+ }
+ $this->assertFalse($fileEntry->isDirectory());
+ $this->assertFalse($fileEntry->isReadOnly());
+ $this->assertFalse($fileEntry->isReadOnly());
+ }
+
+ /**
+ * @dataProvider nameProvider
+ */
+ public function testStat($name) {
+ $txtFile = $this->getTextFile();
+ $size = filesize($txtFile);
+
+ $this->share->put($txtFile, $this->root . '/' . $name);
+ unlink($txtFile);
+
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertEquals($size, $info->getSize());
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\NotFoundException
+ */
+ public function testStatNonExisting() {
+ $this->share->stat($this->root . '/fo.txt');
+ }
+
+ /**
+ * note setting archive and system bit is not supported
+ *
+ * @dataProvider nameProvider
+ */
+ public function testSetMode($name) {
+ $txtFile = $this->getTextFile();
+
+ $this->share->put($txtFile, $this->root . '/' . $name);
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_NORMAL);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertFalse($info->isReadOnly());
+ $this->assertFalse($info->isArchived());
+ $this->assertFalse($info->isSystem());
+ $this->assertFalse($info->isHidden());
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_READONLY);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertTrue($info->isReadOnly());
+ $this->assertFalse($info->isArchived());
+ $this->assertFalse($info->isSystem());
+ $this->assertFalse($info->isHidden());
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_ARCHIVE);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertFalse($info->isReadOnly());
+ $this->assertTrue($info->isArchived());
+ $this->assertFalse($info->isSystem());
+ $this->assertFalse($info->isHidden());
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_READONLY | FileInfo::MODE_ARCHIVE);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertTrue($info->isReadOnly());
+ $this->assertTrue($info->isArchived());
+ $this->assertFalse($info->isSystem());
+ $this->assertFalse($info->isHidden());
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_HIDDEN);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertFalse($info->isReadOnly());
+ $this->assertFalse($info->isArchived());
+ $this->assertFalse($info->isSystem());
+ $this->assertTrue($info->isHidden());
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_SYSTEM);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertFalse($info->isReadOnly());
+ $this->assertFalse($info->isArchived());
+ $this->assertTrue($info->isSystem());
+ $this->assertFalse($info->isHidden());
+
+ $this->share->setMode($this->root . '/' . $name, FileInfo::MODE_NORMAL);
+ $info = $this->share->stat($this->root . '/' . $name);
+ $this->assertFalse($info->isReadOnly());
+ $this->assertFalse($info->isArchived());
+ $this->assertFalse($info->isSystem());
+ $this->assertFalse($info->isHidden());
+ }
+
+ public function pathProvider() {
+ // / ? < > \ : * | " are illegal characters in path on windows
+ return array(
+ array('dir/sub/foo.txt'),
+ array('bar.txt'),
+ array("single'quote'/sub/foo.txt"),
+ array('日本語/url %2F +encode/asd.txt'),
+ array(
+ 'a somewhat longer folder than the other with more charaters as the all the other filenames/' .
+ 'followed by a somewhat long file name after that.txt'
+ )
+ );
+ }
+
+ /**
+ * @dataProvider pathProvider
+ */
+ public function testSubDirs($path) {
+ $dirs = explode('/', $path);
+ $name = array_pop($dirs);
+ $fullPath = '';
+ foreach ($dirs as $dir) {
+ $fullPath .= '/' . $dir;
+ $this->share->mkdir($this->root . $fullPath);
+ }
+ $txtFile = $this->getTextFile();
+ $size = filesize($txtFile);
+ $this->share->put($txtFile, $this->root . $fullPath . '/' . $name);
+ unlink($txtFile);
+ $info = $this->share->stat($this->root . $fullPath . '/' . $name);
+ $this->assertEquals($size, $info->getSize());
+ $this->assertFalse($info->isHidden());
+ }
+
+ public function testDelAfterStat() {
+ $name = 'foo.txt';
+ $txtFile = $this->getTextFile();
+
+ $this->share->put($txtFile, $this->root . '/' . $name);
+ unlink($txtFile);
+
+ $this->share->stat($this->root . '/' . $name);
+ $this->share->del($this->root . '/foo.txt');
+ }
+
+ /**
+ * @param $name
+ * @dataProvider nameProvider
+ */
+ public function testDirPaths($name) {
+ $txtFile = $this->getTextFile();
+ $this->share->mkdir($this->root . '/' . $name);
+ $this->share->put($txtFile, $this->root . '/' . $name . '/' . $name);
+ unlink($txtFile);
+
+ $content = $this->share->dir($this->root . '/' . $name);
+ $this->assertCount(1, $content);
+ $this->assertEquals($name, $content[0]->getName());
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php b/apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php
new file mode 100644
index 00000000000..d8e10235c12
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/NativeShare.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Test;
+
+use Icewind\SMB\NativeServer;
+
+class NativeShare extends AbstractShare {
+ public function setUp() {
+ if (!function_exists('smbclient_state_new')) {
+ $this->markTestSkipped('libsmbclient php extension not installed');
+ }
+ $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+ $this->server = new NativeServer($this->config->host, $this->config->user, $this->config->password);
+ $this->share = $this->server->getShare($this->config->share);
+ if ($this->config->root) {
+ $this->root = '/' . $this->config->root . '/' . uniqid();
+ } else {
+ $this->root = '/' . uniqid();
+ }
+ $this->share->mkdir($this->root);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php b/apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php
new file mode 100644
index 00000000000..2d7b62fedeb
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/NativeStream.php
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Test;
+
+use Icewind\SMB\NativeServer;
+
+class NativeStream extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var \Icewind\SMB\Server $server
+ */
+ protected $server;
+
+ /**
+ * @var \Icewind\SMB\NativeShare $share
+ */
+ protected $share;
+
+ /**
+ * @var string $root
+ */
+ protected $root;
+
+ protected $config;
+
+ public function setUp() {
+ if (!function_exists('smbclient_state_new')) {
+ $this->markTestSkipped('libsmbclient php extension not installed');
+ }
+ $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+ $this->server = new NativeServer($this->config->host, $this->config->user, $this->config->password);
+ $this->share = $this->server->getShare($this->config->share);
+ if ($this->config->root) {
+ $this->root = '/' . $this->config->root . '/' . uniqid();
+ } else {
+ $this->root = '/' . uniqid();
+ }
+ $this->share->mkdir($this->root);
+ }
+
+ private function getTextFile() {
+ $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua';
+ $file = tempnam('/tmp', 'smb_test_');
+ file_put_contents($file, $text);
+ return $file;
+ }
+
+ public function testSeekTell() {
+ $sourceFile = $this->getTextFile();
+ $this->share->put($sourceFile, $this->root . '/foobar');
+ $fh = $this->share->read($this->root . '/foobar');
+ $content = fread($fh, 3);
+ $this->assertEquals('Lor', $content);
+
+ fseek($fh, -2, SEEK_CUR);
+
+ $content = fread($fh, 3);
+ $this->assertEquals('ore', $content);
+
+ fseek($fh, 3, SEEK_SET);
+
+ $content = fread($fh, 3);
+ $this->assertEquals('em ', $content);
+
+ fseek($fh, -3, SEEK_END);
+
+ $content = fread($fh, 3);
+ $this->assertEquals('qua', $content);
+
+ fseek($fh, -3, SEEK_END);
+ $this->assertEquals(120, ftell($fh));
+ }
+
+ public function testStat() {
+ $sourceFile = $this->getTextFile();
+ $this->share->put($sourceFile, $this->root . '/foobar');
+ $fh = $this->share->read($this->root . '/foobar');
+ $stat = fstat($fh);
+ $this->assertEquals(filesize($sourceFile), $stat['size']);
+ unlink($sourceFile);
+ }
+
+ public function testTruncate() {
+ if (version_compare(phpversion(), '5.4.0', '<')) {
+ $this->markTestSkipped('php <5.4 doesn\'t support truncate for stream wrappers');
+ }
+ $fh = $this->share->write($this->root . '/foobar');
+ fwrite($fh, 'foobar');
+ ftruncate($fh, 3);
+ fclose($fh);
+
+ $fh = $this->share->read($this->root . '/foobar');
+ $this->assertEquals('foo', stream_get_contents($fh));
+ }
+
+ public function testEOF() {
+ if (version_compare(phpversion(), '5.4.0', '<')) {
+ $this->markTestSkipped('php <5.4 doesn\'t support truncate for stream wrappers');
+ }
+ $fh = $this->share->write($this->root . '/foobar');
+ fwrite($fh, 'foobar');
+ fclose($fh);
+
+ $fh = $this->share->read($this->root . '/foobar');
+ fread($fh, 3);
+ $this->assertFalse(feof($fh));
+ fread($fh, 5);
+ $this->assertTrue(feof($fh));
+ }
+
+ public function testLockUnsupported() {
+ $fh = $this->share->write($this->root . '/foobar');
+ $this->assertFalse(flock($fh, LOCK_SH));
+ }
+
+ public function testSetOptionUnsupported() {
+ $fh = $this->share->write($this->root . '/foobar');
+ $this->assertFalse(stream_set_blocking($fh, false));
+ }
+
+ public function tearDown() {
+ if ($this->share) {
+ $this->cleanDir($this->root);
+ }
+ unset($this->share);
+ }
+
+ public function cleanDir($dir) {
+ $content = $this->share->dir($dir);
+ foreach ($content as $metadata) {
+ if ($metadata->isDirectory()) {
+ $this->cleanDir($metadata->getPath());
+ } else {
+ $this->share->del($metadata->getPath());
+ }
+ }
+ $this->share->rmdir($dir);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/Parser.php b/apps/files_external/3rdparty/icewind/smb/tests/Parser.php
new file mode 100644
index 00000000000..0dd06d6af33
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/Parser.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Test;
+
+
+use Icewind\SMB\FileInfo;
+
+class Parser extends \PHPUnit_Framework_TestCase {
+ public function modeProvider() {
+ return array(
+ array('D', FileInfo::MODE_DIRECTORY),
+ array('A', FileInfo::MODE_ARCHIVE),
+ array('S', FileInfo::MODE_SYSTEM),
+ array('H', FileInfo::MODE_HIDDEN),
+ array('R', FileInfo::MODE_READONLY),
+ array('N', FileInfo::MODE_NORMAL),
+ array('RA', FileInfo::MODE_READONLY | FileInfo::MODE_ARCHIVE),
+ array('RAH', FileInfo::MODE_READONLY | FileInfo::MODE_ARCHIVE | FileInfo::MODE_HIDDEN)
+ );
+ }
+
+ /**
+ * @dataProvider modeProvider
+ */
+ public function testParseMode($string, $mode) {
+ $parser = new \Icewind\SMB\Parser('UTC');
+ $this->assertEquals($mode, $parser->parseMode($string), 'Failed parsing ' . $string);
+ }
+
+ public function statProvider() {
+ return array(
+ array(
+ array(
+ 'altname: test.txt',
+ 'create_time: Sat Oct 12 07:05:58 PM 2013 CEST',
+ 'access_time: Tue Oct 15 02:58:48 PM 2013 CEST',
+ 'write_time: Sat Oct 12 07:05:58 PM 2013 CEST',
+ 'change_time: Sat Oct 12 07:05:58 PM 2013 CEST',
+ 'attributes: (80)',
+ 'stream: [::$DATA], 29634 bytes'
+ ),
+ array(
+ 'mtime' => strtotime('12 Oct 2013 19:05:58 CEST'),
+ 'mode' => FileInfo::MODE_NORMAL,
+ 'size' => 29634
+ ))
+ );
+ }
+
+ /**
+ * @dataProvider statProvider
+ */
+ public function testStat($output, $stat) {
+ $parser = new \Icewind\SMB\Parser('UTC');
+ $this->assertEquals($stat, $parser->parseStat($output));
+ }
+
+ public function dirProvider() {
+ return array(
+ array(
+ array(
+ ' . D 0 Tue Aug 26 19:11:56 2014',
+ ' .. DR 0 Sun Oct 28 15:24:02 2012',
+ ' c.pdf N 29634 Sat Oct 12 19:05:58 2013',
+ '',
+ ' 62536 blocks of size 8388608. 57113 blocks available'
+ ),
+ array(
+ new FileInfo('/c.pdf', 'c.pdf', 29634, strtotime('12 Oct 2013 19:05:58 CEST'), FileInfo::MODE_NORMAL)
+ )
+ )
+ );
+ }
+
+ /**
+ * @dataProvider dirProvider
+ */
+ public function testDir($output, $dir) {
+ $parser = new \Icewind\SMB\Parser('CEST');
+ $this->assertEquals($dir, $parser->parseDir($output, ''));
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/Server.php b/apps/files_external/3rdparty/icewind/smb/tests/Server.php
new file mode 100644
index 00000000000..9f62886654f
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/Server.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Test;
+
+class Server extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var \Icewind\SMB\Server $server
+ */
+ private $server;
+
+ private $config;
+
+ public function setUp() {
+ $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+ $this->server = new \Icewind\SMB\Server($this->config->host, $this->config->user, $this->config->password);
+ }
+
+ public function testListShares() {
+ $shares = $this->server->listShares();
+ foreach ($shares as $share) {
+ if ($share->getName() === $this->config->share) {
+ return;
+ }
+ }
+ $this->fail('Share "' . $this->config->share . '" not found');
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\AuthenticationException
+ */
+ public function testWrongUserName() {
+ $this->markTestSkipped('This fails for no reason on travis');
+ $server = new \Icewind\SMB\Server($this->config->host, uniqid(), uniqid());
+ $server->listShares();
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\AuthenticationException
+ */
+ public function testWrongPassword() {
+ $server = new \Icewind\SMB\Server($this->config->host, $this->config->user, uniqid());
+ $server->listShares();
+ }
+
+ /**
+ * @expectedException \Icewind\SMB\Exception\InvalidHostException
+ */
+ public function testWrongHost() {
+ $server = new \Icewind\SMB\Server(uniqid(), $this->config->user, $this->config->password);
+ $server->listShares();
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/Share.php b/apps/files_external/3rdparty/icewind/smb/tests/Share.php
new file mode 100644
index 00000000000..a629914d748
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/Share.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\SMB\Test;
+
+use Icewind\SMB\Server as NormalServer;
+
+class Share extends AbstractShare {
+ public function setUp() {
+ $this->config = json_decode(file_get_contents(__DIR__ . '/config.json'));
+ $this->server = new NormalServer($this->config->host, $this->config->user, $this->config->password);
+ $this->share = $this->server->getShare($this->config->share);
+ if ($this->config->root) {
+ $this->root = '/' . $this->config->root . '/' . uniqid();
+ } else {
+ $this->root = '/' . uniqid();
+ }
+ $this->share->mkdir($this->root);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php b/apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php
new file mode 100644
index 00000000000..dc2e34b183e
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/bootstrap.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+date_default_timezone_set('UTC');
+require_once __DIR__.'/../vendor/autoload.php';
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/config.json b/apps/files_external/3rdparty/icewind/smb/tests/config.json
new file mode 100644
index 00000000000..0ecd7e3715d
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/config.json
@@ -0,0 +1,7 @@
+{
+ "host": "localhost",
+ "user": "test",
+ "password": "test",
+ "share": "test",
+ "root": "test"
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml b/apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml
new file mode 100644
index 00000000000..3ab244dd34f
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/tests/phpunit.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<phpunit bootstrap="bootstrap.php">
+ <testsuite name='SMB'>
+ <directory suffix='.php'>./</directory>
+ </testsuite>
+</phpunit>
diff --git a/apps/files_external/3rdparty/icewind/streams/.gitignore b/apps/files_external/3rdparty/icewind/streams/.gitignore
new file mode 100644
index 00000000000..4f389129e2d
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/.gitignore
@@ -0,0 +1,3 @@
+.idea
+vendor
+composer.lock
diff --git a/apps/files_external/3rdparty/icewind/streams/.travis.yml b/apps/files_external/3rdparty/icewind/streams/.travis.yml
new file mode 100644
index 00000000000..dfa52767dda
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/.travis.yml
@@ -0,0 +1,26 @@
+language: php
+php:
+ - 5.3
+ - 5.4
+ - 5.5
+ - hhvm
+
+matrix:
+ allow_failures:
+ - php: hhvm # due to facebook/hhvm#3321
+
+env:
+ global:
+ - CURRENT_DIR=`pwd`
+
+install:
+ - composer install --dev --no-interaction
+
+script:
+ - mkdir -p build/logs
+ - cd tests
+ - phpunit --coverage-clover ../build/logs/clover.xml --configuration phpunit.xml
+
+after_script:
+ - cd $CURRENT_DIR
+ - php vendor/bin/coveralls -v
diff --git a/apps/files_external/3rdparty/icewind/streams/README.md b/apps/files_external/3rdparty/icewind/streams/README.md
new file mode 100644
index 00000000000..54f6d19a560
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/README.md
@@ -0,0 +1,52 @@
+#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)
+
+Generic stream wrappers for php.
+
+##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
+
+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###
+```php
+<?php
+
+use \Icewind\Streams\CallBackWrapper;
+
+require('vendor/autoload.php');
+
+// get an existing stream to wrap
+$source = fopen('php://temp', 'r+');
+
+// register the callbacks
+$stream = CallbackWrapper::wrap($source,
+ // read callback
+ function ($count) {
+ echo "read " . $count . "bytes\n";
+ },
+ // write callback
+ function ($data) {
+ echo "wrote '" . $data . "'\n";
+ },
+ // close callback
+ function () {
+ echo "stream closed\n";
+ });
+
+fwrite($stream, 'some dummy data');
+
+rewind($stream);
+fread($stream, 5);
+
+fclose($stream);
+```
+
+Note: due to php's internal stream buffering the `$count` passed to the read callback
+will be equal to php's internal buffer size (8192 on default) an not the number of bytes
+requested by `fopen()`
diff --git a/apps/files_external/3rdparty/icewind/streams/composer.json b/apps/files_external/3rdparty/icewind/streams/composer.json
new file mode 100644
index 00000000000..86d3c834258
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/composer.json
@@ -0,0 +1,23 @@
+{
+ "name" : "icewind/streams",
+ "description" : "A set of generic stream wrappers",
+ "license" : "MIT",
+ "authors" : [
+ {
+ "name" : "Robin Appelman",
+ "email": "icewind@owncloud.com"
+ }
+ ],
+ "require" : {
+ "php": ">=5.3"
+ },
+ "require-dev" : {
+ "satooshi/php-coveralls": "dev-master"
+ },
+ "autoload" : {
+ "psr-4": {
+ "Icewind\\Streams\\Tests\\": "tests/",
+ "Icewind\\Streams\\": "src/"
+ }
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
new file mode 100644
index 00000000000..fd99aa6ebe8
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/CallbackWrapper.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Wrapper that provides callbacks for write, read and close
+ *
+ * The following options should be passed in the context when opening the stream
+ * [
+ * 'callback' => [
+ * 'source' => resource
+ * 'read' => function($count){} (optional)
+ * 'write' => function($data){} (optional)
+ * 'close' => function(){} (optional)
+ * ]
+ * ]
+ *
+ * All callbacks are called after the operation is executed on the source stream
+ */
+class CallbackWrapper extends Wrapper {
+ /**
+ * @var callable
+ */
+ protected $readCallback;
+
+ /**
+ * @var callable
+ */
+ protected $writeCallback;
+
+ /**
+ * @var callable
+ */
+ protected $closeCallback;
+
+ /**
+ * Wraps a stream with the provided callbacks
+ *
+ * @param resource $source
+ * @param callable $read (optional)
+ * @param callable $write (optional)
+ * @param callable $close (optional)
+ * @return resource
+ *
+ * @throws \BadMethodCallException
+ */
+ public static function wrap($source, $read = null, $write = null, $close = null) {
+ $context = stream_context_create(array(
+ 'callback' => array(
+ 'source' => $source,
+ 'read' => $read,
+ 'write' => $write,
+ 'close' => $close
+ )
+ ));
+ stream_wrapper_register('callback', '\Icewind\Streams\CallbackWrapper');
+ try {
+ $wrapped = fopen('callback://', 'r+', false, $context);
+ } catch (\BadMethodCallException $e) {
+ stream_wrapper_unregister('callback');
+ throw $e;
+ }
+ stream_wrapper_unregister('callback');
+ return $wrapped;
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ $context = $this->loadContext('callback');
+
+ if (isset($context['read']) and is_callable($context['read'])) {
+ $this->readCallback = $context['read'];
+ }
+ if (isset($context['write']) and is_callable($context['write'])) {
+ $this->writeCallback = $context['write'];
+ }
+ if (isset($context['close']) and is_callable($context['close'])) {
+ $this->closeCallback = $context['close'];
+ }
+ return true;
+ }
+
+ public function stream_read($count) {
+ $result = parent::stream_read($count);
+ if ($this->readCallback) {
+ call_user_func($this->readCallback, $count);
+ }
+ return $result;
+ }
+
+ public function stream_write($data) {
+ $result = parent::stream_write($data);
+ if ($this->writeCallback) {
+ call_user_func($this->writeCallback, $data);
+ }
+ return $result;
+ }
+
+ public function stream_close() {
+ $result = parent::stream_close();
+ if ($this->closeCallback) {
+ call_user_func($this->closeCallback);
+ }
+ return $result;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Directory.php b/apps/files_external/3rdparty/icewind/streams/src/Directory.php
new file mode 100644
index 00000000000..c80a878386b
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/Directory.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Interface for stream wrappers that implements a directory
+ */
+interface Directory {
+ /**
+ * @param string $path
+ * @param array $options
+ * @return bool
+ */
+ public function dir_opendir($path, $options);
+
+ /**
+ * @return string
+ */
+ public function dir_readdir();
+
+ /**
+ * @return bool
+ */
+ public function dir_closedir();
+
+ /**
+ * @return bool
+ */
+ public function dir_rewinddir();
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/File.php b/apps/files_external/3rdparty/icewind/streams/src/File.php
new file mode 100644
index 00000000000..6202ef4a4b4
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/File.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Interface for stream wrappers that implements a file
+ */
+interface File {
+ /**
+ * @param string $path
+ * @param string $mode
+ * @param int $options
+ * @param string &$opened_path
+ * @return bool
+ */
+ public function stream_open($path, $mode, $options, &$opened_path);
+
+ /**
+ * @param string $offset
+ * @param int $whence
+ * @return bool
+ */
+ public function stream_seek($offset, $whence = SEEK_SET);
+
+ /**
+ * @return int
+ */
+ public function stream_tell();
+
+ /**
+ * @param int $count
+ * @return string
+ */
+ public function stream_read($count);
+
+ /**
+ * @param string $data
+ * @return int
+ */
+ public function stream_write($data);
+
+ /**
+ * @param int $option
+ * @param int $arg1
+ * @param int $arg2
+ * @return bool
+ */
+ public function stream_set_option($option, $arg1, $arg2);
+
+ /**
+ * @param int $size
+ * @return bool
+ */
+ public function stream_truncate($size);
+
+ /**
+ * @return array
+ */
+ public function stream_stat();
+
+ /**
+ * @param int $operation
+ * @return bool
+ */
+ public function stream_lock($operation);
+
+ /**
+ * @return bool
+ */
+ public function stream_flush();
+
+ /**
+ * @return bool
+ */
+ public function stream_eof();
+
+ /**
+ * @return bool
+ */
+ public function stream_close();
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
new file mode 100644
index 00000000000..c4eac5d4ed3
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/IteratorDirectory.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Create a directory handle from an iterator or array
+ *
+ * The following options should be passed in the context when opening the stream
+ * [
+ * 'dir' => [
+ * 'array' => string[]
+ * 'iterator' => \Iterator
+ * ]
+ * ]
+ *
+ * Either 'array' or 'iterator' need to be set, if both are set, 'iterator' takes preference
+ */
+class IteratorDirectory implements Directory {
+ /**
+ * @var resource
+ */
+ public $context;
+
+ /**
+ * @var \Iterator
+ */
+ protected $iterator;
+
+ /**
+ * 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['iterator']) and $context['iterator'] instanceof \Iterator) {
+ $this->iterator = $context['iterator'];
+ } else if (isset($context['array']) and is_array($context['array'])) {
+ $this->iterator = new \ArrayIterator($context['array']);
+ } else {
+ throw new \BadMethodCallException('Invalid context, iterator or array not set');
+ }
+ return $context;
+ }
+
+ /**
+ * @param string $path
+ * @param array $options
+ * @return bool
+ */
+ public function dir_opendir($path, $options) {
+ $this->loadContext('dir');
+ return true;
+ }
+
+ /**
+ * @return string
+ */
+ public function dir_readdir() {
+ if ($this->iterator->valid()) {
+ $result = $this->iterator->current();
+ $this->iterator->next();
+ return $result;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @return bool
+ */
+ public function dir_closedir() {
+ return true;
+ }
+
+ /**
+ * @return bool
+ */
+ public function dir_rewinddir() {
+ $this->iterator->rewind();
+ return true;
+ }
+
+ /**
+ * Creates a directory handle from the provided array or iterator
+ *
+ * @param \Iterator | array $source
+ * @return resource
+ *
+ * @throws \BadMethodCallException
+ */
+ public static function wrap($source) {
+ if ($source instanceof \Iterator) {
+ $context = stream_context_create(array(
+ 'dir' => array(
+ 'iterator' => $source)
+ ));
+ } else if (is_array($source)) {
+ $context = stream_context_create(array(
+ 'dir' => array(
+ '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;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
new file mode 100644
index 00000000000..8cbaaa756d3
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/NullWrapper.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * 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)
+ ));
+ stream_wrapper_register('null', '\Icewind\Streams\NullWrapper');
+ try {
+ $wrapped = fopen('null://', 'r+', false, $context);
+ } catch (\BadMethodCallException $e) {
+ stream_wrapper_unregister('null');
+ throw $e;
+ }
+ stream_wrapper_unregister('null');
+ return $wrapped;
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path) {
+ $this->loadContext('null');
+ return true;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
new file mode 100644
index 00000000000..2e3a6e6cd88
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/src/Wrapper.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams;
+
+/**
+ * Base class for stream wrappers, wraps an existing stream
+ *
+ * This wrapper itself doesn't implement any functionality but is just a base class for other wrappers to extend
+ */
+abstract class Wrapper implements File {
+ /**
+ * @var resource
+ */
+ public $context;
+
+ /**
+ * The wrapped stream
+ *
+ * @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, "callable" options not set');
+ }
+ if (isset($context['source']) and is_resource($context['source'])) {
+ $this->setSourceStream($context['source']);
+ } else {
+ throw new \BadMethodCallException('Invalid context, source not set');
+ }
+ 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;
+ }
+
+ public function stream_tell() {
+ return ftell($this->source);
+ }
+
+ public function stream_read($count) {
+ return fread($this->source, $count);
+ }
+
+ public function stream_write($data) {
+ return fwrite($this->source, $data);
+ }
+
+ public function stream_set_option($option, $arg1, $arg2) {
+ switch ($option) {
+ case STREAM_OPTION_BLOCKING:
+ stream_set_blocking($this->source, $arg1);
+ break;
+ case STREAM_OPTION_READ_TIMEOUT:
+ stream_set_timeout($this->source, $arg1, $arg2);
+ break;
+ case STREAM_OPTION_WRITE_BUFFER:
+ stream_set_write_buffer($this->source, $arg1);
+ }
+ }
+
+ public function stream_truncate($size) {
+ return ftruncate($this->source, $size);
+ }
+
+ public function stream_stat() {
+ return fstat($this->source);
+ }
+
+ public function stream_lock($mode) {
+ return flock($this->source, $mode);
+ }
+
+ public function stream_flush() {
+ return fflush($this->source);
+ }
+
+ public function stream_eof() {
+ return feof($this->source);
+ }
+
+ public function stream_close() {
+ return fclose($this->source);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php b/apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php
new file mode 100644
index 00000000000..229b629dcd9
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/tests/CallbackWrapper.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams\Tests;
+
+class CallbackWrapper extends Wrapper {
+
+ /**
+ * @param resource $source
+ * @param callable $read
+ * @param callable $write
+ * @param callable $close
+ * @return resource
+ */
+ protected function wrapSource($source, $read = null, $write = null, $close = null) {
+ return \Icewind\Streams\CallbackWrapper::wrap($source, $read, $write, $close);
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testWrapInvalidSource() {
+ $this->wrapSource('foo');
+ }
+
+ public function testReadCallback() {
+ $called = false;
+ $callBack = function () use (&$called) {
+ $called = true;
+ };
+
+ $source = fopen('php://temp', 'r+');
+ fwrite($source, 'foobar');
+ rewind($source);
+
+ $wrapped = $this->wrapSource($source, $callBack);
+ $this->assertEquals('foo', fread($wrapped, 3));
+ $this->assertTrue($called);
+ }
+
+ public function testWriteCallback() {
+ $lastData = '';
+ $callBack = function ($data) use (&$lastData) {
+ $lastData = $data;
+ };
+
+ $source = fopen('php://temp', 'r+');
+
+ $wrapped = $this->wrapSource($source, null, $callBack);
+ fwrite($wrapped, 'foobar');
+ $this->assertEquals('foobar', $lastData);
+ }
+
+ public function testCloseCallback() {
+ $called = false;
+ $callBack = function () use (&$called) {
+ $called = true;
+ };
+
+ $source = fopen('php://temp', 'r+');
+ fwrite($source, 'foobar');
+ rewind($source);
+
+ $wrapped = $this->wrapSource($source, null, null, $callBack);
+ fclose($wrapped);
+ $this->assertTrue($called);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php b/apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php
new file mode 100644
index 00000000000..0d990468368
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/tests/IteratorDirectory.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams\Tests;
+
+class IteratorDirectory extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @param \Iterator | array $source
+ * @return resource
+ */
+ protected function wrapSource($source) {
+ return \Icewind\Streams\IteratorDirectory::wrap($source);
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testNoContext() {
+ $context = stream_context_create(array());
+ stream_wrapper_register('iterator', '\Icewind\Streams\IteratorDirectory');
+ try {
+ opendir('iterator://', $context);
+ stream_wrapper_unregister('iterator');
+ } catch (\Exception $e) {
+ stream_wrapper_unregister('iterator');
+ throw $e;
+ }
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testInvalidSource() {
+ $context = stream_context_create(array(
+ 'dir' => array(
+ 'array' => 2
+ )
+ ));
+ stream_wrapper_register('iterator', '\Icewind\Streams\IteratorDirectory');
+ try {
+ opendir('iterator://', $context);
+ stream_wrapper_unregister('iterator');
+ } catch (\Exception $e) {
+ stream_wrapper_unregister('iterator');
+ throw $e;
+ }
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testWrapInvalidSource() {
+ $this->wrapSource(2);
+ }
+
+ public function fileListProvider() {
+ $longList = array_fill(0, 500, 'foo');
+ return array(
+ array(
+ array(
+ 'foo',
+ 'bar',
+ 'qwerty'
+ )
+ ),
+ array(
+ array(
+ 'with spaces',
+ 'under_scores',
+ '日本語',
+ 'character %$_',
+ '.',
+ '0',
+ 'double "quotes"',
+ "single 'quotes'"
+ )
+ ),
+ array(
+ array(
+ 'single item'
+ )
+ ),
+ array(
+ $longList
+ ),
+ array(
+ array()
+ )
+ );
+ }
+
+ protected function basicTest($fileList, $dh) {
+ $result = array();
+
+ while (($file = readdir($dh)) !== false) {
+ $result[] = $file;
+ }
+
+ $this->assertEquals($fileList, $result);
+
+ rewinddir($dh);
+ if (count($fileList)) {
+ $this->assertEquals($fileList[0], readdir($dh));
+ } else {
+ $this->assertFalse(readdir($dh));
+ }
+ }
+
+ /**
+ * @dataProvider fileListProvider
+ */
+ public function testBasicIterator($fileList) {
+ $iterator = new \ArrayIterator($fileList);
+ $dh = $this->wrapSource($iterator);
+ $this->basicTest($fileList, $dh);
+ }
+
+ /**
+ * @dataProvider fileListProvider
+ */
+ public function testBasicArray($fileList) {
+ $dh = $this->wrapSource($fileList);
+ $this->basicTest($fileList, $dh);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php b/apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php
new file mode 100644
index 00000000000..ba42b4dfea1
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/tests/NullWrapper.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams\Tests;
+
+class NullWrapper extends Wrapper {
+
+ /**
+ * @param resource $source
+ * @return resource
+ */
+ protected function wrapSource($source) {
+ return \Icewind\Streams\NullWrapper::wrap($source);
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testNoContext() {
+ stream_wrapper_register('null', '\Icewind\Streams\NullWrapper');
+ $context = stream_context_create(array());
+ try {
+ fopen('null://', 'r+', false, $context);
+ stream_wrapper_unregister('null');
+ } catch (\Exception $e) {
+ stream_wrapper_unregister('null');
+ throw $e;
+ }
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testNoSource() {
+ stream_wrapper_register('null', '\Icewind\Streams\NullWrapper');
+ $context = stream_context_create(array(
+ 'null' => array(
+ 'source' => 'bar'
+ )
+ ));
+ try {
+ fopen('null://', 'r+', false, $context);
+ } catch (\Exception $e) {
+ stream_wrapper_unregister('null');
+ throw $e;
+ }
+ }
+
+ /**
+ * @expectedException \BadMethodCallException
+ */
+ public function testWrapInvalidSource() {
+ $this->wrapSource('foo');
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php b/apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php
new file mode 100644
index 00000000000..6bb644dd611
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/tests/Wrapper.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+namespace Icewind\Streams\Tests;
+
+abstract class Wrapper extends \PHPUnit_Framework_TestCase {
+ /**
+ * @param resource $source
+ * @return resource
+ */
+ abstract protected function wrapSource($source);
+
+ public function testRead() {
+ $source = fopen('php://temp', 'r+');
+ fwrite($source, 'foobar');
+ rewind($source);
+
+ $wrapped = $this->wrapSource($source);
+ $this->assertEquals('foo', fread($wrapped, 3));
+ $this->assertEquals('bar', fread($wrapped, 3));
+ $this->assertEquals('', fread($wrapped, 3));
+ }
+
+ public function testWrite() {
+ $source = fopen('php://temp', 'r+');
+ rewind($source);
+
+ $wrapped = $this->wrapSource($source);
+
+ $this->assertEquals(6, fwrite($wrapped, 'foobar'));
+ rewind($source);
+ $this->assertEquals('foobar', stream_get_contents($source));
+ }
+
+ public function testClose() {
+ $source = fopen('php://temp', 'r+');
+ rewind($source);
+
+ $wrapped = $this->wrapSource($source);
+
+ fclose($wrapped);
+ $this->assertFalse(is_resource($source));
+ }
+
+ public function testSeekTell() {
+ $source = fopen('php://temp', 'r+');
+ fwrite($source, 'foobar');
+ rewind($source);
+
+ $wrapped = $this->wrapSource($source);
+
+ $this->assertEquals(0, ftell($wrapped));
+
+ fseek($wrapped, 2);
+ $this->assertEquals(2, ftell($source));
+ $this->assertEquals(2, ftell($wrapped));
+
+ fseek($wrapped, 2, SEEK_CUR);
+ $this->assertEquals(4, ftell($source));
+ $this->assertEquals(4, ftell($wrapped));
+
+ fseek($wrapped, -1, SEEK_END);
+ $this->assertEquals(5, ftell($source));
+ $this->assertEquals(5, ftell($wrapped));
+ }
+
+ public function testStat() {
+ $source = fopen(__FILE__, 'r+');
+ $wrapped = $this->wrapSource($source);
+ $this->assertEquals(stat(__FILE__), fstat($wrapped));
+ }
+
+ public function testTruncate() {
+ if (version_compare(phpversion(), '5.4.0', '<')) {
+ $this->markTestSkipped('php <5.4 doesn\'t support truncate for stream wrappers');
+ }
+ $source = fopen('php://temp', 'r+');
+ fwrite($source, 'foobar');
+ rewind($source);
+ $wrapped = $this->wrapSource($source);
+
+ ftruncate($wrapped, 2);
+ $this->assertEquals('fo', fread($wrapped, 10));
+ }
+
+ public function testLock() {
+ $source = tmpfile();
+ $wrapped = $this->wrapSource($source);
+ if (!flock($wrapped, LOCK_EX)) {
+ $this->fail('Unable to acquire lock');
+ }
+ }
+
+ public function testStreamOptions() {
+ $source = fopen('php://temp', 'r+');
+ $wrapped = $this->wrapSource($source);
+ stream_set_blocking($wrapped, 0);
+ stream_set_timeout($wrapped, 1, 0);
+ stream_set_write_buffer($wrapped, 0);
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php b/apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php
new file mode 100644
index 00000000000..2c17fd57feb
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/tests/bootstrap.php
@@ -0,0 +1,9 @@
+<?php
+/**
+ * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ */
+
+date_default_timezone_set('UTC');
+require_once __DIR__ . '/../vendor/autoload.php';
diff --git a/apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml b/apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml
new file mode 100644
index 00000000000..e3d96352c43
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/streams/tests/phpunit.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<phpunit bootstrap="bootstrap.php">
+ <testsuite name='Stream'>
+ <directory suffix='.php'>./</directory>
+ </testsuite>
+</phpunit>
diff --git a/apps/files_external/3rdparty/smb4php/smb.php b/apps/files_external/3rdparty/smb4php/smb.php
deleted file mode 100644
index e325506fa14..00000000000
--- a/apps/files_external/3rdparty/smb4php/smb.php
+++ /dev/null
@@ -1,516 +0,0 @@
-<?php
-###################################################################
-# smb.php
-# This class implements a SMB stream wrapper based on 'smbclient'
-#
-# Date: lun oct 22 10:35:35 CEST 2007
-#
-# Homepage: http://www.phpclasses.org/smb4php
-#
-# Copyright (c) 2007 Victor M. Varela <vmvarela@gmail.com>
-# Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
-# Copyright (c) 2014 Robin McCorkell <rmccorkell@karoshi.org.uk>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# 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 General Public License for more details.
-#
-# On the official website http://www.phpclasses.org/smb4php the
-# license is listed as LGPL so we assume that this is
-# dual-licensed GPL/LGPL
-###################################################################
-
-define ('SMB4PHP_VERSION', '0.8');
-
-###################################################################
-# CONFIGURATION SECTION - Change for your needs
-###################################################################
-
-define ('SMB4PHP_SMBCLIENT', 'smbclient');
-define ('SMB4PHP_SMBOPTIONS', 'TCP_NODELAY IPTOS_LOWDELAY SO_KEEPALIVE SO_RCVBUF=8192 SO_SNDBUF=8192');
-define ('SMB4PHP_AUTHMODE', 'arg'); # set to 'env' to use USER enviroment variable
-
-###################################################################
-# SMB - commands that does not need an instance
-###################################################################
-
-$GLOBALS['__smb_cache'] = array ('stat' => array (), 'dir' => array ());
-
-class smb {
-
- private static $regexp = array (
- '^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip',
- 'Anonymous login successful' => 'skip',
- '^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip',
- '^\tSharename[ ]+Type[ ]+Comment$' => 'shares',
- '^\t---------[ ]+----[ ]+-------$' => 'skip',
- '^\tServer [ ]+Comment$' => 'servers',
- '^\t---------[ ]+-------$' => 'skip',
- '^\tWorkgroup[ ]+Master$' => 'workg',
- '^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip',
- '^\tIPC\\\$(.*)[ ]+IPC' => 'skip',
- '^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share',
- '^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip',
- '([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip',
- 'Got a positive name query response from ' => 'skip',
- '^(session setup failed): (.*)$' => 'error',
- '^(.*): ERRSRV - ERRbadpw' => 'error',
- '^Error returning browse list: (.*)$' => 'error',
- '^tree connect failed: (.*)$' => 'error',
- '^(Connection to .* failed)(.*)$' => 'error-connect',
- '^NT_STATUS_(.*) ' => 'error',
- '^NT_STATUS_(.*)\$' => 'error',
- 'ERRDOS - ERRbadpath \((.*).\)' => 'error',
- 'cd (.*): (.*)$' => 'error',
- '^cd (.*): NT_STATUS_(.*)' => 'error',
- '^\t(.*)$' => 'srvorwg',
- '^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip',
- '^Job ([0-9]+) cancelled' => 'skip',
- '^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files',
- '^message start: ERRSRV - (ERRmsgoff)' => 'error'
- );
-
- function getRegexp() {
- return self::$regexp;
- }
-
- function parse_url ($url) {
- $pu = parse_url (trim($url));
- foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) {
- if (! isset($pu[$i])) {
- $pu[$i] = '';
- }
- }
- if (count ($userdomain = explode (';', urldecode ($pu['user']))) > 1) {
- @list ($pu['domain'], $pu['user']) = $userdomain;
- }
- $path = preg_replace (array ('/^\//', '/\/$/'), '', urldecode ($pu['path']));
- list ($pu['share'], $pu['path']) = (preg_match ('/^([^\/]+)\/(.*)/', $path, $regs))
- ? array ($regs[1], preg_replace ('/\//', '\\', $regs[2]))
- : array ($path, '');
- $pu['type'] = $pu['path'] ? 'path' : ($pu['share'] ? 'share' : ($pu['host'] ? 'host' : '**error**'));
- if (! ($pu['port'] = intval(@$pu['port']))) {
- $pu['port'] = 139;
- }
-
- // decode user and password
- $pu['user'] = urldecode($pu['user']);
- $pu['pass'] = urldecode($pu['pass']);
- return $pu;
- }
-
-
- function look ($purl) {
- return smb::client ('-L ' . escapeshellarg ($purl['host']), $purl);
- }
-
-
- function execute ($command, $purl, $regexp = NULL) {
- return smb::client ('-d 0 '
- . escapeshellarg ('//' . $purl['host'] . '/' . $purl['share'])
- . ' -c ' . escapeshellarg ($command), $purl, $regexp
- );
- }
-
- function client ($params, $purl, $regexp = NULL) {
-
- if ($regexp === NULL) $regexp = smb::$regexp;
-
- if (SMB4PHP_AUTHMODE == 'env') {
- putenv("USER={$purl['user']}%{$purl['pass']}");
- $auth = '';
- } else {
- $auth = ($purl['user'] <> '' ? (' -U ' . escapeshellarg ($purl['user'] . '%' . $purl['pass'])) : '');
- }
- if ($purl['domain'] <> '') {
- $auth .= ' -W ' . escapeshellarg ($purl['domain']);
- }
- $port = ($purl['port'] <> 139 ? ' -p ' . escapeshellarg ($purl['port']) : '');
- $options = '-O ' . escapeshellarg(SMB4PHP_SMBOPTIONS);
-
- // this put env is necessary to read the output of smbclient correctly
- $old_locale = getenv('LC_ALL');
- putenv('LC_ALL=en_US.UTF-8');
- $output = popen ('TZ=UTC '.SMB4PHP_SMBCLIENT." -N {$auth} {$options} {$port} {$options} {$params} 2>/dev/null", 'r');
- $gotInfo = false;
- $info = array ();
- $info['info']= array ();
- $mode = '';
- while ($line = fgets ($output, 4096)) {
- list ($tag, $regs, $i) = array ('skip', array (), array ());
- reset ($regexp);
- foreach ($regexp as $r => $t) if (preg_match ('/'.$r.'/', $line, $regs)) {
- $tag = $t;
- break;
- }
- switch ($tag) {
- case 'skip': continue;
- case 'shares': $mode = 'shares'; break;
- case 'servers': $mode = 'servers'; break;
- case 'workg': $mode = 'workgroups'; break;
- case 'share':
- list($name, $type) = array (
- trim(substr($line, 1, 15)),
- trim(strtolower(substr($line, 17, 10)))
- );
- $i = ($type <> 'disk' && preg_match('/^(.*) Disk/', $line, $regs))
- ? array(trim($regs[1]), 'disk')
- : array($name, 'disk');
- break;
- case 'srvorwg':
- list ($name, $master) = array (
- strtolower(trim(substr($line,1,21))),
- strtolower(trim(substr($line, 22)))
- );
- $i = ($mode == 'servers') ? array ($name, "server") : array ($name, "workgroup", $master);
- break;
- case 'files':
- list ($attr, $name) = preg_match ("/^(.*)[ ]+([D|A|H|N|S|R]+)$/", trim ($regs[1]), $regs2)
- ? array (trim ($regs2[2]), trim ($regs2[1]))
- : array ('', trim ($regs[1]));
- list ($his, $im) = array (
- explode(':', $regs[6]), 1 + strpos("JanFebMarAprMayJunJulAugSepOctNovDec", $regs[4]) / 3);
- $i = ($name <> '.' && $name <> '..')
- ? array (
- $name,
- (strpos($attr,'D') === FALSE) ? 'file' : 'folder',
- 'attr' => $attr,
- 'size' => intval($regs[2]),
- 'time' => mktime ($his[0], $his[1], $his[2], $im, $regs[5], $regs[7])
- )
- : array();
- break;
- case 'error':
- if(substr($regs[0],0,22)=='NT_STATUS_NO_SUCH_FILE'){
- return false;
- }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_NAME_COLLISION'){
- return false;
- }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_PATH_NOT_FOUND'){
- return false;
- }elseif(substr($regs[0],0,31)=='NT_STATUS_OBJECT_NAME_NOT_FOUND'){
- return false;
- }elseif(substr($regs[0],0,29)=='NT_STATUS_FILE_IS_A_DIRECTORY'){
- return false;
- }
- trigger_error($regs[0].' params('.$params.')', E_USER_ERROR);
- case 'error-connect':
- // connection error can happen after obtaining share list if
- // NetBIOS is disabled/blocked on the target server,
- // in which case we keep the info and continue
- if (!$gotInfo) {
- return false;
- }
- }
- if ($i) switch ($i[1]) {
- case 'file':
- case 'folder': $info['info'][$i[0]] = $i;
- case 'disk':
- case 'server':
- case 'workgroup': $info[$i[1]][] = $i[0];
- $gotInfo = true;
- }
- }
- pclose($output);
-
-
- // restore previous locale
- if ($old_locale===false) {
- putenv('LC_ALL');
- } else {
- putenv('LC_ALL='.$old_locale);
- }
-
- return $info;
- }
-
-
- # stats
-
- function url_stat ($url, $flags = STREAM_URL_STAT_LINK) {
- if ($s = smb::getstatcache($url)) {
- return $s;
- }
- list ($stat, $pu) = array (false, smb::parse_url ($url));
- switch ($pu['type']) {
- case 'host':
- if ($o = smb::look ($pu))
- $stat = stat ("/tmp");
- else
- trigger_error ("url_stat(): list failed for host '{$pu['host']}'", E_USER_WARNING);
- break;
- case 'share':
- if (smb::execute("ls", $pu))
- $stat = stat ("/tmp");
- else
- trigger_error ("url_stat(): disk resource '{$pu['share']}' not found in '{$pu['host']}'", E_USER_WARNING);
- break;
- case 'path':
- if ($o = smb::execute ('dir "'.$pu['path'].'"', $pu)) {
- $p = explode('\\', $pu['path']);
- $name = $p[count($p)-1];
- if (isset ($o['info'][$name])) {
- $stat = smb::addstatcache ($url, $o['info'][$name]);
- } else {
- trigger_error ("url_stat(): path '{$pu['path']}' not found", E_USER_WARNING);
- }
- } else {
- return false;
-// trigger_error ("url_stat(): dir failed for path '{$pu['path']}'", E_USER_WARNING);
- }
- break;
- default: trigger_error ('error in URL', E_USER_ERROR);
- }
- return $stat;
- }
-
- function addstatcache ($url, $info) {
- $url = str_replace('//', '/', $url);
- $url = rtrim($url, '/');
- global $__smb_cache;
- $is_file = (strpos ($info['attr'],'D') === FALSE);
- $s = ($is_file) ? stat ('/etc/passwd') : stat ('/tmp');
- $s[7] = $s['size'] = $info['size'];
- $s[8] = $s[9] = $s[10] = $s['atime'] = $s['mtime'] = $s['ctime'] = $info['time'];
- return $__smb_cache['stat'][$url] = $s;
- }
-
- function getstatcache ($url) {
- $url = str_replace('//', '/', $url);
- $url = rtrim($url, '/');
- global $__smb_cache;
- return isset ($__smb_cache['stat'][$url]) ? $__smb_cache['stat'][$url] : FALSE;
- }
-
- function clearstatcache ($url='') {
- $url = str_replace('//', '/', $url);
- $url = rtrim($url, '/');
- global $__smb_cache;
- if ($url == '') $__smb_cache['stat'] = array (); else unset ($__smb_cache['stat'][$url]);
- }
-
-
- # commands
-
- function unlink ($url) {
- $pu = smb::parse_url($url);
- if ($pu['type'] <> 'path') trigger_error('unlink(): error in URL', E_USER_ERROR);
- smb::clearstatcache ($url);
- smb_stream_wrapper::cleardircache (dirname($url));
- return smb::execute ('del "'.$pu['path'].'"', $pu);
- }
-
- function rename ($url_from, $url_to) {
- $replace = false;
- list ($from, $to) = array (smb::parse_url($url_from), smb::parse_url($url_to));
- if ($from['host'] <> $to['host'] ||
- $from['share'] <> $to['share'] ||
- $from['user'] <> $to['user'] ||
- $from['pass'] <> $to['pass'] ||
- $from['domain'] <> $to['domain']) {
- trigger_error('rename(): FROM & TO must be in same server-share-user-pass-domain', E_USER_ERROR);
- }
- if ($from['type'] <> 'path' || $to['type'] <> 'path') {
- trigger_error('rename(): error in URL', E_USER_ERROR);
- }
- smb::clearstatcache ($url_from);
- $cmd = '';
- // check if target file exists
- if (smb::url_stat($url_to)) {
- // delete target file first
- $cmd = 'del "' . $to['path'] . '"; ';
- $replace = true;
- }
- $cmd .= 'rename "' . $from['path'] . '" "' . $to['path'] . '"';
- $result = smb::execute($cmd, $to);
- if ($replace) {
- // clear again, else the cache will return the info
- // from the old file
- smb::clearstatcache ($url_to);
- }
- return $result !== false;
- }
-
- function mkdir ($url, $mode, $options) {
- $pu = smb::parse_url($url);
- if ($pu['type'] <> 'path') trigger_error('mkdir(): error in URL', E_USER_ERROR);
- return smb::execute ('mkdir "'.$pu['path'].'"', $pu)!==false;
- }
-
- function rmdir ($url) {
- $pu = smb::parse_url($url);
- if ($pu['type'] <> 'path') trigger_error('rmdir(): error in URL', E_USER_ERROR);
- smb::clearstatcache ($url);
- smb_stream_wrapper::cleardircache (dirname($url));
- return smb::execute ('rmdir "'.$pu['path'].'"', $pu)!==false;
- }
-
-}
-
-###################################################################
-# SMB_STREAM_WRAPPER - class to be registered for smb:// URLs
-###################################################################
-
-class smb_stream_wrapper extends smb {
-
- # variables
-
- private $stream, $url, $parsed_url = array (), $mode, $tmpfile;
- private $need_flush = FALSE;
- private $dir = array (), $dir_index = -1;
-
-
- # directories
-
- function dir_opendir ($url, $options) {
- if ($d = $this->getdircache ($url)) {
- $this->dir = $d;
- $this->dir_index = 0;
- return TRUE;
- }
- $pu = smb::parse_url ($url);
- switch ($pu['type']) {
- case 'host':
- if ($o = smb::look ($pu)) {
- $this->dir = $o['disk'];
- $this->dir_index = 0;
- } else {
- trigger_error ("dir_opendir(): list failed for host '{$pu['host']}'", E_USER_WARNING);
- return false;
- }
- break;
- case 'share':
- case 'path':
- if (is_array($o = smb::execute ('dir "'.$pu['path'].'\*"', $pu))) {
- $this->dir = array_keys($o['info']);
- $this->dir_index = 0;
- $this->adddircache ($url, $this->dir);
- if(substr($url,-1,1)=='/'){
- $url=substr($url,0,-1);
- }
- foreach ($o['info'] as $name => $info) {
- smb::addstatcache($url . '/' . $name, $info);
- }
- } else {
- trigger_error ("dir_opendir(): dir failed for path '".$pu['path']."'", E_USER_WARNING);
- return false;
- }
- break;
- default:
- trigger_error ('dir_opendir(): error in URL', E_USER_ERROR);
- return false;
- }
- return TRUE;
- }
-
- function dir_readdir () {
- return ($this->dir_index < count($this->dir)) ? $this->dir[$this->dir_index++] : FALSE;
- }
-
- function dir_rewinddir () { $this->dir_index = 0; }
-
- function dir_closedir () { $this->dir = array(); $this->dir_index = -1; return TRUE; }
-
-
- # cache
-
- function adddircache ($url, $content) {
- $url = str_replace('//', '/', $url);
- $url = rtrim($url, '/');
- global $__smb_cache;
- return $__smb_cache['dir'][$url] = $content;
- }
-
- function getdircache ($url) {
- $url = str_replace('//', '/', $url);
- $url = rtrim($url, '/');
- global $__smb_cache;
- return isset ($__smb_cache['dir'][$url]) ? $__smb_cache['dir'][$url] : FALSE;
- }
-
- function cleardircache ($url='') {
- $url = str_replace('//', '/', $url);
- $url = rtrim($url, '/');
- global $__smb_cache;
- if ($url == ''){
- $__smb_cache['dir'] = array ();
- }else{
- unset ($__smb_cache['dir'][$url]);
- }
- }
-
-
- # streams
-
- function stream_open ($url, $mode, $options, $opened_path) {
- $this->url = $url;
- $this->mode = $mode;
- $this->parsed_url = $pu = smb::parse_url($url);
- if ($pu['type'] <> 'path') trigger_error('stream_open(): error in URL', E_USER_ERROR);
- switch ($mode) {
- case 'r':
- case 'r+':
- case 'rb':
- case 'a':
- case 'a+': $this->tmpfile = tempnam('/tmp', 'smb.down.');
- $result = smb::execute ('get "'.$pu['path'].'" "'.$this->tmpfile.'"', $pu);
- if($result === false){
- return $result;
- }
- break;
- case 'w':
- case 'w+':
- case 'wb':
- case 'x':
- case 'x+': $this->cleardircache();
- $this->tmpfile = tempnam('/tmp', 'smb.up.');
- $this->need_flush=true;
- }
- $this->stream = fopen ($this->tmpfile, $mode);
- return TRUE;
- }
-
- function stream_close () { return fclose($this->stream); }
-
- function stream_read ($count) { return fread($this->stream, $count); }
-
- function stream_write ($data) { $this->need_flush = TRUE; return fwrite($this->stream, $data); }
-
- function stream_eof () { return feof($this->stream); }
-
- function stream_tell () { return ftell($this->stream); }
-
- // PATCH: the wrapper must return true when fseek succeeded by returning 0.
- function stream_seek ($offset, $whence=null) { return fseek($this->stream, $offset, $whence) === 0; }
-
- function stream_flush () {
- if ($this->mode <> 'r' && $this->need_flush) {
- smb::clearstatcache ($this->url);
- smb::execute ('put "'.$this->tmpfile.'" "'.$this->parsed_url['path'].'"', $this->parsed_url);
- $this->need_flush = FALSE;
- }
- }
-
- function stream_stat () { return smb::url_stat ($this->url); }
-
- function __destruct () {
- if ($this->tmpfile <> '') {
- if ($this->need_flush) $this->stream_flush ();
- unlink ($this->tmpfile);
-
- }
- }
-
-}
-
-###################################################################
-# Register 'smb' protocol !
-###################################################################
-
-stream_wrapper_register('smb', 'smb_stream_wrapper')
- or die ('Failed to register protocol');
diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php
index 70f6b0159a6..e74ce3594c1 100644
--- a/apps/files_external/appinfo/app.php
+++ b/apps/files_external/appinfo/app.php
@@ -22,6 +22,8 @@ OC::$CLASSPATH['OC\Files\Storage\SFTP_Key'] = 'files_external/lib/sftp_key.php';
OC::$CLASSPATH['OC_Mount_Config'] = 'files_external/lib/config.php';
OC::$CLASSPATH['OCA\Files\External\Api'] = 'files_external/lib/api.php';
+require_once __DIR__ . '/../3rdparty/autoload.php';
+
OCP\App::registerAdmin('files_external', 'settings');
if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == 'yes') {
OCP\App::registerPersonal('files_external', 'personal');
diff --git a/apps/files_external/l10n/cs_CZ.js b/apps/files_external/l10n/cs_CZ.js
index 52e9217a601..b89623a1673 100644
--- a/apps/files_external/l10n/cs_CZ.js
+++ b/apps/files_external/l10n/cs_CZ.js
@@ -53,6 +53,8 @@ OC.L10N.register(
"All users. Type to select user or group." : "Všichni uživatelé. Začněte psát pro výběr uživatelů a skupin.",
"(group)" : "(skupina)",
"Saved" : "Uloženo",
+ "Generate keys" : "Vytvořit klíče",
+ "Error generating key pair" : "Chyba při vytváření párů klíče",
"<b>Note:</b> " : "<b>Poznámka:</b>",
"and" : "a",
"<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Poznámka:</b> cURL podpora v PHP není povolena nebo nainstalována. Není možné připojení %s. Prosím požádejte svého správce systému ať ji nainstaluje.",
diff --git a/apps/files_external/l10n/cs_CZ.json b/apps/files_external/l10n/cs_CZ.json
index 6b7ea9460a7..ceade182add 100644
--- a/apps/files_external/l10n/cs_CZ.json
+++ b/apps/files_external/l10n/cs_CZ.json
@@ -51,6 +51,8 @@
"All users. Type to select user or group." : "Všichni uživatelé. Začněte psát pro výběr uživatelů a skupin.",
"(group)" : "(skupina)",
"Saved" : "Uloženo",
+ "Generate keys" : "Vytvořit klíče",
+ "Error generating key pair" : "Chyba při vytváření párů klíče",
"<b>Note:</b> " : "<b>Poznámka:</b>",
"and" : "a",
"<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>Poznámka:</b> cURL podpora v PHP není povolena nebo nainstalována. Není možné připojení %s. Prosím požádejte svého správce systému ať ji nainstaluje.",
diff --git a/apps/files_external/l10n/gl.js b/apps/files_external/l10n/gl.js
index 7d1687f8385..b2a4770a389 100644
--- a/apps/files_external/l10n/gl.js
+++ b/apps/files_external/l10n/gl.js
@@ -50,7 +50,7 @@ OC.L10N.register(
"Error configuring Google Drive storage" : "Produciuse un erro ao configurar o almacenamento en Google Drive",
"Personal" : "Persoal",
"System" : "Sistema",
- "All users. Type to select user or group." : "Todos os usuarios. Escriba para selecionar usuario ou grupo.",
+ "All users. Type to select user or group." : "Todos os usuarios. Escriba para seleccionar usuario ou grupo.",
"(group)" : "(grupo)",
"Saved" : "Gardado",
"Generate keys" : "Xerar chaves",
diff --git a/apps/files_external/l10n/gl.json b/apps/files_external/l10n/gl.json
index f8356aaac31..08d1c457168 100644
--- a/apps/files_external/l10n/gl.json
+++ b/apps/files_external/l10n/gl.json
@@ -48,7 +48,7 @@
"Error configuring Google Drive storage" : "Produciuse un erro ao configurar o almacenamento en Google Drive",
"Personal" : "Persoal",
"System" : "Sistema",
- "All users. Type to select user or group." : "Todos os usuarios. Escriba para selecionar usuario ou grupo.",
+ "All users. Type to select user or group." : "Todos os usuarios. Escriba para seleccionar usuario ou grupo.",
"(group)" : "(grupo)",
"Saved" : "Gardado",
"Generate keys" : "Xerar chaves",
diff --git a/apps/files_external/l10n/ja.js b/apps/files_external/l10n/ja.js
index 492b0fb7336..17990d68e08 100644
--- a/apps/files_external/l10n/ja.js
+++ b/apps/files_external/l10n/ja.js
@@ -53,6 +53,8 @@ OC.L10N.register(
"All users. Type to select user or group." : "すべてのユーザー。ユーザー、グループを追加",
"(group)" : "(グループ)",
"Saved" : "保存されました",
+ "Generate keys" : "キーを生成",
+ "Error generating key pair" : "キーペアの生成エラー",
"<b>Note:</b> " : "<b>注意:</b> ",
"and" : "と",
"<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b> PHPにcURLのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。",
diff --git a/apps/files_external/l10n/ja.json b/apps/files_external/l10n/ja.json
index 5ef73a75c77..af817743f27 100644
--- a/apps/files_external/l10n/ja.json
+++ b/apps/files_external/l10n/ja.json
@@ -51,6 +51,8 @@
"All users. Type to select user or group." : "すべてのユーザー。ユーザー、グループを追加",
"(group)" : "(グループ)",
"Saved" : "保存されました",
+ "Generate keys" : "キーを生成",
+ "Error generating key pair" : "キーペアの生成エラー",
"<b>Note:</b> " : "<b>注意:</b> ",
"and" : "と",
"<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b> PHPにcURLのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。",
diff --git a/apps/files_external/lib/sftp.php b/apps/files_external/lib/sftp.php
index 2a762ad068f..c021f778feb 100644
--- a/apps/files_external/lib/sftp.php
+++ b/apps/files_external/lib/sftp.php
@@ -25,16 +25,8 @@ class SFTP extends \OC\Files\Storage\Common {
private static $tempFiles = array();
public function __construct($params) {
- // The sftp:// scheme has to be manually registered via inclusion of
- // the 'Net/SFTP/Stream.php' file which registers the Net_SFTP_Stream
- // stream wrapper as a side effect.
- // A slightly better way to register the stream wrapper is available
- // since phpseclib 0.3.7 in the form of a static call to
- // Net_SFTP_Stream::register() which will trigger autoloading if
- // necessary.
- // TODO: Call Net_SFTP_Stream::register() instead when phpseclib is
- // updated to 0.3.7 or higher.
- require_once 'Net/SFTP/Stream.php';
+ // Register sftp://
+ \Net_SFTP_Stream::register();
$this->host = $params['host'];
$proto = strpos($this->host, '://');
diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php
index 3f0b0f45bfb..c554eaf19ee 100644
--- a/apps/files_external/lib/smb.php
+++ b/apps/files_external/lib/smb.php
@@ -8,139 +8,273 @@
namespace OC\Files\Storage;
-require_once __DIR__ . '/../3rdparty/smb4php/smb.php';
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Exception\NotFoundException;
+use Icewind\SMB\NativeServer;
+use Icewind\SMB\Server;
+use Icewind\Streams\CallbackWrapper;
+use Icewind\Streams\IteratorDirectory;
+use OC\Files\Filesystem;
-class SMB extends \OC\Files\Storage\StreamWrapper{
- private $password;
- private $user;
- private $host;
- private $root;
- private $share;
+class SMB extends Common {
+ /**
+ * @var \Icewind\SMB\Server
+ */
+ protected $server;
+
+ /**
+ * @var \Icewind\SMB\Share
+ */
+ protected $share;
+
+ /**
+ * @var \Icewind\SMB\FileInfo[]
+ */
+ protected $statCache = array();
public function __construct($params) {
if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
- $this->host=$params['host'];
- $this->user=$params['user'];
- $this->password=$params['password'];
- $this->share=$params['share'];
- $this->root=isset($params['root'])?$params['root']:'/';
- if ( ! $this->root || $this->root[0]!='/') {
- $this->root='/'.$this->root;
- }
- if (substr($this->root, -1, 1)!='/') {
- $this->root.='/';
+ if (Server::NativeAvailable()) {
+ $this->server = new NativeServer($params['host'], $params['user'], $params['password']);
+ } else {
+ $this->server = new Server($params['host'], $params['user'], $params['password']);
}
- if ( ! $this->share || $this->share[0]!='/') {
- $this->share='/'.$this->share;
+ $this->share = $this->server->getShare(trim($params['share'], '/'));
+
+ $this->root = isset($params['root']) ? $params['root'] : '/';
+ if (!$this->root || $this->root[0] != '/') {
+ $this->root = '/' . $this->root;
}
- if (substr($this->share, -1, 1)=='/') {
- $this->share = substr($this->share, 0, -1);
+ if (substr($this->root, -1, 1) != '/') {
+ $this->root .= '/';
}
} else {
throw new \Exception('Invalid configuration');
}
}
- public function getId(){
- return 'smb::' . $this->user . '@' . $this->host . '/' . $this->share . '/' . $this->root;
+ /**
+ * @return string
+ */
+ public function getId() {
+ return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '/' . $this->share->getName() . '/' . $this->root;
}
- public function constructUrl($path) {
- if (substr($path, -1)=='/') {
- $path = substr($path, 0, -1);
- }
- if (substr($path, 0, 1)=='/') {
- $path = substr($path, 1);
+ /**
+ * @param string $path
+ * @return string
+ */
+ protected function buildPath($path) {
+ return Filesystem::normalizePath($this->root . '/' . $path);
+ }
+
+ /**
+ * @param string $path
+ * @return \Icewind\SMB\IFileInfo
+ */
+ protected function getFileInfo($path) {
+ $path = $this->buildPath($path);
+ if (!isset($this->statCache[$path])) {
+ $this->statCache[$path] = $this->share->stat($path);
}
- // remove trailing dots which some versions of samba don't seem to like
- $path = rtrim($path, '.');
- $path = urlencode($path);
- $user = urlencode($this->user);
- $pass = urlencode($this->password);
- return 'smb://'.$user.':'.$pass.'@'.$this->host.$this->share.$this->root.$path;
+ return $this->statCache[$path];
}
- public function stat($path) {
- if ( ! $path and $this->root=='/') {//mtime doesn't work for shares
- $stat=stat($this->constructUrl($path));
- if (empty($stat)) {
- return false;
- }
- $mtime=$this->shareMTime();
- $stat['mtime']=$mtime;
- return $stat;
- } else {
- $stat = stat($this->constructUrl($path));
+ /**
+ * @param string $path
+ * @return \Icewind\SMB\IFileInfo[]
+ */
+ protected function getFolderContents($path) {
+ $path = $this->buildPath($path);
+ $files = $this->share->dir($path);
+ foreach ($files as $file) {
+ $this->statCache[$path . '/' . $file->getName()] = $file;
+ }
+ return $files;
+ }
- // smb4php can return an empty array if the connection could not be established
- if (empty($stat)) {
- return false;
- }
+ /**
+ * @param \Icewind\SMB\IFileInfo $info
+ * @return array
+ */
+ protected function formatInfo($info) {
+ return array(
+ 'size' => $info->getSize(),
+ 'mtime' => $info->getMTime()
+ );
+ }
- return $stat;
- }
+ /**
+ * @param string $path
+ * @return array
+ */
+ public function stat($path) {
+ return $this->formatInfo($this->getFileInfo($path));
}
/**
- * Unlinks file or directory
* @param string $path
+ * @return bool
*/
public function unlink($path) {
- if ($this->is_dir($path)) {
- $this->rmdir($path);
- }
- else {
- $url = $this->constructUrl($path);
- unlink($url);
- clearstatcache(false, $url);
+ try {
+ if ($this->is_dir($path)) {
+ return $this->rmdir($path);
+ } else {
+ $path = $this->buildPath($path);
+ unset($this->statCache[$path]);
+ $this->share->del($path);
+ return true;
+ }
+ } catch (NotFoundException $e) {
+ return false;
}
- // smb4php still returns false even on success so
- // check here whether file was really deleted
- return !file_exists($path);
}
/**
* check if a file or folder has been updated since $time
+ *
* @param string $path
* @param int $time
* @return bool
*/
- public function hasUpdated($path,$time) {
- if(!$path and $this->root=='/') {
+ public function hasUpdated($path, $time) {
+ if (!$path and $this->root == '/') {
// mtime doesn't work for shares, but giving the nature of the backend,
// doing a full update is still just fast enough
return true;
} else {
- $actualTime=$this->filemtime($path);
- return $actualTime>$time;
+ $actualTime = $this->filemtime($path);
+ return $actualTime > $time;
}
}
/**
- * get the best guess for the modification time of the share
+ * @param string $path
+ * @param string $mode
+ * @return resource
*/
- private function shareMTime() {
- $dh=$this->opendir('');
- $lastCtime=0;
- if(is_resource($dh)) {
- while (($file = readdir($dh)) !== false) {
- if ($file!='.' and $file!='..') {
- $ctime=$this->filemtime($file);
- if ($ctime>$lastCtime) {
- $lastCtime=$ctime;
+ public function fopen($path, $mode) {
+ $fullPath = $this->buildPath($path);
+ try {
+ switch ($mode) {
+ case 'r':
+ case 'rb':
+ if (!$this->file_exists($path)) {
+ return false;
+ }
+ return $this->share->read($fullPath);
+ case 'w':
+ case 'wb':
+ return $this->share->write($fullPath);
+ case 'a':
+ case 'ab':
+ case 'r+':
+ case 'w+':
+ case 'wb+':
+ case 'a+':
+ case 'x':
+ case 'x+':
+ case 'c':
+ case 'c+':
+ //emulate these
+ if (strrpos($path, '.') !== false) {
+ $ext = substr($path, strrpos($path, '.'));
+ } else {
+ $ext = '';
}
+ if ($this->file_exists($path)) {
+ if (!$this->isUpdatable($path)) {
+ return false;
+ }
+ $tmpFile = $this->getCachedFile($path);
+ } else {
+ if (!$this->isCreatable(dirname($path))) {
+ return false;
+ }
+ $tmpFile = \OCP\Files::tmpFile($ext);
+ }
+ $source = fopen($tmpFile, $mode);
+ $share = $this->share;
+ return CallBackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
+ $share->put($tmpFile, $fullPath);
+ unlink($tmpFile);
+ });
+ }
+ return false;
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ }
+
+ public function rmdir($path) {
+ try {
+ $this->statCache = array();
+ $content = $this->share->dir($this->buildPath($path));
+ foreach ($content as $file) {
+ if ($file->isDirectory()) {
+ $this->rmdir($path . '/' . $file->getName());
+ } else {
+ $this->share->del($file->getPath());
}
}
+ $this->share->rmdir($this->buildPath($path));
+ return true;
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ }
+
+ public function touch($path, $time = null) {
+ if (!$this->file_exists($path)) {
+ $fh = $this->share->write($this->buildPath($path));
+ fclose($fh);
+ return true;
+ }
+ return false;
+ }
+
+ public function opendir($path) {
+ $files = $this->getFolderContents($path);
+ $names = array_map(function ($info) {
+ /** @var \Icewind\SMB\IFileInfo $info */
+ return $info->getName();
+ }, $files);
+ return IteratorDirectory::wrap($names);
+ }
+
+ public function filetype($path) {
+ try {
+ return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
+ } catch (NotFoundException $e) {
+ return false;
+ }
+ }
+
+ public function mkdir($path) {
+ $path = $this->buildPath($path);
+ try {
+ $this->share->mkdir($path);
+ return true;
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+
+ public function file_exists($path) {
+ try {
+ $this->getFileInfo($path);
+ return true;
+ } catch (NotFoundException $e) {
+ return false;
}
- return $lastCtime;
}
/**
* check if smbclient is installed
*/
public static function checkDependencies() {
- $smbClientExists = (bool) \OC_Helper::findBinaryPath('smbclient');
+ $smbClientExists = (bool)\OC_Helper::findBinaryPath('smbclient');
return $smbClientExists ? true : array('smbclient');
}
-
}
diff --git a/apps/files_external/lib/smb_oc.php b/apps/files_external/lib/smb_oc.php
index a7c93d97fd1..245d1ed79b3 100644
--- a/apps/files_external/lib/smb_oc.php
+++ b/apps/files_external/lib/smb_oc.php
@@ -8,9 +8,12 @@
namespace OC\Files\Storage;
-require_once __DIR__ . '/../3rdparty/smb4php/smb.php';
-class SMB_OC extends \OC\Files\Storage\SMB {
+use Icewind\SMB\Exception\AccessDeniedException;
+use Icewind\SMB\Exception\Exception;
+use Icewind\SMB\Server;
+
+class SMB_OC extends SMB {
private $username_as_share;
/**
@@ -19,18 +22,18 @@ class SMB_OC extends \OC\Files\Storage\SMB {
*/
public function __construct($params) {
if (isset($params['host']) && \OC::$server->getSession()->exists('smb-credentials')) {
- $host=$params['host'];
+ $host = $params['host'];
$this->username_as_share = ($params['username_as_share'] === 'true');
$params_auth = json_decode(\OC::$server->getCrypto()->decrypt(\OC::$server->getSession()->get('smb-credentials')), true);
$user = \OC::$server->getSession()->get('loginname');
$password = $params_auth['password'];
- $root=isset($params['root'])?$params['root']:'/';
+ $root = isset($params['root']) ? $params['root'] : '/';
$share = '';
if ($this->username_as_share) {
- $share = '/'.$user;
+ $share = '/' . $user;
} elseif (isset($params['share'])) {
$share = $params['share'];
} else {
@@ -84,33 +87,15 @@ class SMB_OC extends \OC\Files\Storage\SMB {
}
return false;
} else {
- $smb = new \smb();
- $pu = $smb->parse_url($this->constructUrl(''));
-
- // Attempt to connect anonymously
- $pu['user'] = '';
- $pu['pass'] = '';
-
- // Share cannot be checked if dynamic
- if ($this->username_as_share) {
- if ($smb->look($pu)) {
- return true;
- } else {
- return false;
- }
- }
- if (!$pu['share']) {
- return false;
- }
-
- // The following error messages are expected due to anonymous login
- $regexp = array(
- '(NT_STATUS_ACCESS_DENIED)' => 'skip'
- ) + $smb->getRegexp();
+ $server = new Server($this->server->getHost(), '', '');
- if ($smb->client("-d 0 " . escapeshellarg('//' . $pu['host'] . '/' . $pu['share']) . " -c exit", $pu, $regexp)) {
+ try {
+ $server->listShares();
return true;
- } else {
+ } catch (AccessDeniedException $e) {
+ // expected due to anonymous login
+ return true;
+ } catch (Exception $e) {
return false;
}
}
diff --git a/apps/files_external/tests/backends/ftp.php b/apps/files_external/tests/backends/ftp.php
index 842b7f43fa8..d62759889b1 100644
--- a/apps/files_external/tests/backends/ftp.php
+++ b/apps/files_external/tests/backends/ftp.php
@@ -15,12 +15,12 @@ class FTP extends Storage {
parent::setUp();
$id = $this->getUniqueID();
- $this->config = include('files_external/tests/config.php');
- if ( ! is_array($this->config) or ! isset($this->config['ftp']) or ! $this->config['ftp']['run']) {
+ $this->config = include('files_external/tests/config.ftp.php');
+ if ( ! is_array($this->config) or ! $this->config['run']) {
$this->markTestSkipped('FTP backend not configured');
}
- $this->config['ftp']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
- $this->instance = new \OC\Files\Storage\FTP($this->config['ftp']);
+ $this->config['root'] .= '/' . $id; //make sure we have an new empty folder to work in
+ $this->instance = new \OC\Files\Storage\FTP($this->config);
$this->instance->mkdir('/');
}
diff --git a/apps/files_external/tests/backends/smb.php b/apps/files_external/tests/backends/smb.php
index 9e5ab2b331f..4b1150c6a25 100644
--- a/apps/files_external/tests/backends/smb.php
+++ b/apps/files_external/tests/backends/smb.php
@@ -10,24 +10,25 @@ namespace Test\Files\Storage;
class SMB extends Storage {
- private $config;
-
protected function setUp() {
parent::setUp();
$id = $this->getUniqueID();
- $this->config = include('files_external/tests/config.php');
- if (!is_array($this->config) or !isset($this->config['smb']) or !$this->config['smb']['run']) {
+ $config = include('files_external/tests/config.smb.php');
+ if (!is_array($config) or !$config['run']) {
$this->markTestSkipped('Samba backend not configured');
}
- $this->config['smb']['root'] .= $id; //make sure we have an new empty folder to work in
- $this->instance = new \OC\Files\Storage\SMB($this->config['smb']);
+ if (substr($config['root'], -1, 1) != '/') {
+ $config['root'] .= '/';
+ }
+ $config['root'] .= $id; //make sure we have an new empty folder to work in
+ $this->instance = new \OC\Files\Storage\SMB($config);
$this->instance->mkdir('/');
}
protected function tearDown() {
if ($this->instance) {
- \OCP\Files::rmdirr($this->instance->constructUrl(''));
+ $this->instance->rmdir('');
}
parent::tearDown();
diff --git a/apps/files_external/tests/backends/webdav.php b/apps/files_external/tests/backends/webdav.php
index c390612810d..c454c8e4a9d 100644
--- a/apps/files_external/tests/backends/webdav.php
+++ b/apps/files_external/tests/backends/webdav.php
@@ -10,8 +10,6 @@ namespace Test\Files\Storage;
class DAV extends Storage {
- private $config;
-
protected function setUp() {
parent::setUp();
diff --git a/apps/files_external/tests/env/start-ftp-morrisjobke.sh b/apps/files_external/tests/env/start-ftp-morrisjobke.sh
new file mode 100755
index 00000000000..3831e788e5e
--- /dev/null
+++ b/apps/files_external/tests/env/start-ftp-morrisjobke.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# This script start a docker container to test the files_external tests
+# against. It will also change the files_external config to use the docker
+# container as testing environment. This is reverted in the stop step.W
+#
+# Set environment variable DEBUG to print config file
+#
+# @author Morris Jobke
+# @copyright 2015 Morris Jobke <hey@morrisjobke.de>
+#
+
+if ! command -v docker >/dev/null 2>&1; then
+ echo "No docker executable found - skipped docker setup"
+ exit 0;
+fi
+
+echo "Docker executable found - setup docker"
+
+echo "Fetch recent morrisjobke/docker-proftpd docker image"
+docker pull morrisjobke/docker-proftpd
+
+# retrieve current folder to place the config in the parent folder
+thisFolder=`echo $0 | replace "env/start-ftp-morrisjobke.sh" ""`
+
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
+user=test
+password=12345
+
+container=`docker run -d -e USERNAME=$user -e PASSWORD=$password morrisjobke/docker-proftpd`
+
+host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4`
+
+cat > $thisFolder/config.ftp.php <<DELIM
+<?php
+
+return array(
+ 'run'=>true,
+ 'host'=>'$host',
+ 'user'=>'$user',
+ 'password'=>'$password',
+ 'root'=>'',
+);
+
+DELIM
+
+echo "ftp container: $container"
+
+# put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host)
+echo $container >> $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.ftp
+
+if [ -n "$DEBUG" ]; then
+ cat $thisFolder/config.ftp.php
+ cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.ftp
+fi
+
+# TODO find a way to determine the successful initialization inside the docker container
+echo "Waiting 5 seconds for ftp initialization ... "
+sleep 5
+
diff --git a/apps/files_external/tests/env/start-smb-silvershell.sh b/apps/files_external/tests/env/start-smb-silvershell.sh
new file mode 100755
index 00000000000..f72ad3f9e23
--- /dev/null
+++ b/apps/files_external/tests/env/start-smb-silvershell.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# This script start a docker container to test the files_external tests
+# against. It will also change the files_external config to use the docker
+# container as testing environment. This is reverted in the stop step.W
+#
+# Set environment variable DEBUG to print config file
+#
+# @author Morris Jobke
+# @copyright 2015 Morris Jobke <hey@morrisjobke.de>
+#
+
+if ! command -v docker >/dev/null 2>&1; then
+ echo "No docker executable found - skipped docker setup"
+ exit 0;
+fi
+
+echo "Docker executable found - setup docker"
+
+echo "Fetch recent silvershell/samba docker image"
+docker pull silvershell/samba
+
+# retrieve current folder to place the config in the parent folder
+thisFolder=`echo $0 | replace "env/start-smb-silvershell.sh" ""`
+
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
+container=`docker run -d -e SMB_USER=test -e SMB_PWD=test silvershell/samba`
+
+host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4`
+
+cat > $thisFolder/config.smb.php <<DELIM
+<?php
+
+return array(
+ 'run'=>true,
+ 'host'=>'$host',
+ 'user'=>'test',
+ 'password'=>'test',
+ 'root'=>'',
+ 'share'=>'public',
+);
+
+DELIM
+
+echo "samba container: $container"
+
+# put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host)
+echo $container >> $thisFolder/dockerContainerSilvershell.$EXECUTOR_NUMBER.smb
+
+if [ -n "$DEBUG" ]; then
+ cat $thisFolder/config.smb.php
+ cat $thisFolder/dockerContainerSilvershell.$EXECUTOR_NUMBER.smb
+fi
+
+# TODO find a way to determine the successful initialization inside the docker container
+echo "Waiting 5 seconds for smbd initialization ... "
+sleep 5
+
diff --git a/apps/files_external/tests/env/start-webdav-ownCloud.sh b/apps/files_external/tests/env/start-webdav-ownCloud.sh
index c7267cff341..58b87e8f05d 100755
--- a/apps/files_external/tests/env/start-webdav-ownCloud.sh
+++ b/apps/files_external/tests/env/start-webdav-ownCloud.sh
@@ -28,6 +28,10 @@ docker pull morrisjobke/owncloud
# retrieve current folder to place the config in the parent folder
thisFolder=`echo $0 | replace "env/start-webdav-ownCloud.sh" ""`
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
if [ -n "$RUN_DOCKER_MYSQL" ]; then
echo "Fetch recent mysql docker image"
docker pull mysql
@@ -78,5 +82,6 @@ if [ -n "$databaseContainer" ]; then
fi
if [ -n "$DEBUG" ]; then
- echo $thisFolder/config.webdav.php
+ cat $thisFolder/config.webdav.php
+ cat $thisFolder/dockerContainerOwnCloud.$EXECUTOR_NUMBER.webdav
fi
diff --git a/apps/files_external/tests/env/stop-ftp-morrisjobke.sh b/apps/files_external/tests/env/stop-ftp-morrisjobke.sh
new file mode 100755
index 00000000000..d8c6cc4f307
--- /dev/null
+++ b/apps/files_external/tests/env/stop-ftp-morrisjobke.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# This script stops the docker container the files_external tests were run
+# against. It will also revert the config changes done in start step.
+#
+# @author Morris Jobke
+# @copyright 2015 Morris Jobke <hey@morrisjobke.de>
+#
+
+if ! command -v docker >/dev/null 2>&1; then
+ echo "No docker executable found - skipped docker stop"
+ exit 0;
+fi
+
+echo "Docker executable found - stop and remove docker containers"
+
+# retrieve current folder to remove the config from the parent folder
+thisFolder=`echo $0 | replace "env/stop-ftp-morrisjobke.sh" ""`
+
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
+# stopping and removing docker containers
+for container in `cat $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.ftp`; do
+ echo "Stopping and removing docker container $container"
+ # kills running container and removes it
+ docker rm -f $container
+done;
+
+# cleanup
+rm $thisFolder/config.ftp.php
+rm $thisFolder/dockerContainerMorrisJobke.$EXECUTOR_NUMBER.ftp
+
diff --git a/apps/files_external/tests/env/stop-smb-silvershell.sh b/apps/files_external/tests/env/stop-smb-silvershell.sh
new file mode 100755
index 00000000000..6ae28d15506
--- /dev/null
+++ b/apps/files_external/tests/env/stop-smb-silvershell.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# This script stops the docker container the files_external tests were run
+# against. It will also revert the config changes done in start step.
+#
+# @author Morris Jobke
+# @copyright 2015 Morris Jobke <hey@morrisjobke.de>
+#
+
+if ! command -v docker >/dev/null 2>&1; then
+ echo "No docker executable found - skipped docker stop"
+ exit 0;
+fi
+
+echo "Docker executable found - stop and remove docker containers"
+
+# retrieve current folder to remove the config from the parent folder
+thisFolder=`echo $0 | replace "env/stop-smb-silvershell.sh" ""`
+
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
+# stopping and removing docker containers
+for container in `cat $thisFolder/dockerContainerSilvershell.$EXECUTOR_NUMBER.smb`; do
+ echo "Stopping and removing docker container $container"
+ # kills running container and removes it
+ docker rm -f $container
+done;
+
+# cleanup
+rm $thisFolder/config.smb.php
+rm $thisFolder/dockerContainerSilvershell.$EXECUTOR_NUMBER.smb
+
diff --git a/apps/files_external/tests/env/stop-webdav-ownCloud.sh b/apps/files_external/tests/env/stop-webdav-ownCloud.sh
index 2f06eadcf7c..9d75c2bbd03 100755
--- a/apps/files_external/tests/env/stop-webdav-ownCloud.sh
+++ b/apps/files_external/tests/env/stop-webdav-ownCloud.sh
@@ -19,14 +19,9 @@ echo "Docker executable found - stop and remove docker containers"
# retrieve current folder to remove the config from the parent folder
thisFolder=`echo $0 | replace "env/stop-webdav-ownCloud.sh" ""`
-echo "DEBUG"
-
-netstat -tlpen
-
-echo "CONFIG:"
-
-cat $thisFolder/config.webdav.php
-cat $thisFolder/dockerContainerOwnCloud.$EXECUTOR_NUMBER.webdav
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
# stopping and removing docker containers
for container in `cat $thisFolder/dockerContainerOwnCloud.$EXECUTOR_NUMBER.webdav`; do
diff --git a/apps/files_external/tests/smbfunctions.php b/apps/files_external/tests/smbfunctions.php
deleted file mode 100644
index cf9f7cb20fe..00000000000
--- a/apps/files_external/tests/smbfunctions.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-/**
- * Copyright (c) 2013 Vincent Petry <pvince81@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-
-namespace Test\Files\Storage;
-
-class SMBFunctions extends \Test\TestCase {
-
- protected function setUp() {
- parent::setUp();
-
- // dummy config
- $this->config = array(
- 'run'=>false,
- 'user'=>'test',
- 'password'=>'testpassword',
- 'host'=>'smbhost',
- 'share'=>'/sharename',
- 'root'=>'/rootdir/',
- );
-
- $this->instance = new \OC\Files\Storage\SMB($this->config);
- }
-
- public function testGetId() {
- $this->assertEquals('smb::test@smbhost//sharename//rootdir/', $this->instance->getId());
- }
-
- public function testConstructUrl() {
- $this->assertEquals("smb://test:testpassword@smbhost/sharename/rootdir/abc", $this->instance->constructUrl('/abc'));
- $this->assertEquals("smb://test:testpassword@smbhost/sharename/rootdir/abc", $this->instance->constructUrl('/abc/'));
- $this->assertEquals("smb://test:testpassword@smbhost/sharename/rootdir/abc%2F", $this->instance->constructUrl('/abc/.'));
- $this->assertEquals("smb://test:testpassword@smbhost/sharename/rootdir/abc%2Fdef", $this->instance->constructUrl('/abc/def'));
- }
-}
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index 837ceacbab3..8989f8cef2a 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -28,7 +28,10 @@ OCP\Util::addScript('files_sharing', 'external');
OC_FileProxy::register(new OCA\Files\Share\Proxy());
\OC::$server->getActivityManager()->registerExtension(function() {
- return new \OCA\Files_Sharing\Activity();
+ return new \OCA\Files_Sharing\Activity(
+ \OC::$server->query('L10NFactory'),
+ \OC::$server->getURLGenerator()
+ );
});
$config = \OC::$server->getConfig();
diff --git a/apps/files_sharing/l10n/gl.js b/apps/files_sharing/l10n/gl.js
index 36967ee11dd..ada524f78cd 100644
--- a/apps/files_sharing/l10n/gl.js
+++ b/apps/files_sharing/l10n/gl.js
@@ -2,10 +2,10 @@ OC.L10N.register(
"files_sharing",
{
"Server to server sharing is not enabled on this server" : "Neste servidor non está activada a compartición de servidor a servidor",
- "The mountpoint name contains invalid characters." : "O nome do punto de montaxe contén caracteres inválidos.",
+ "The mountpoint name contains invalid characters." : "O nome do punto de montaxe contén caracteres incorrectos",
"Invalid or untrusted SSL certificate" : "Certificado SSL incorrecto ou non fiábel",
- "Could not authenticate to remote share, password might be wrong" : "Non se puido autenticar na compartición remota, o contrasinal podería ser erróneo",
- "Storage not valid" : "Almacenamento non válido",
+ "Could not authenticate to remote share, password might be wrong" : "Non foi pisíbel autenticar na compartición remota, o contrasinal podería ser erróneo",
+ "Storage not valid" : "Almacenamento incorrecto",
"Couldn't add remote share" : "Non foi posíbel engadir a compartición remota",
"Shared with you" : "Compartido con vostede",
"Shared with others" : "Compartido con outros",
@@ -50,7 +50,7 @@ OC.L10N.register(
"Download %s" : "Descargar %s",
"Direct link" : "Ligazón directa",
"Federated Cloud Sharing" : "Compartición de nube federada",
- "Allow users on this server to send shares to other servers" : "Permitir aos ususarios de este servidor enviar comparticións a outros servidores",
- "Allow users on this server to receive shares from other servers" : "Permitir aos usuarios de este servidor recibir comparticións de outros servidores"
+ "Allow users on this server to send shares to other servers" : "Permitir aos usuarios deste servidor enviar comparticións a outros servidores",
+ "Allow users on this server to receive shares from other servers" : "Permitir aos usuarios deste servidor recibir comparticións de outros servidores"
},
"nplurals=2; plural=(n != 1);");
diff --git a/apps/files_sharing/l10n/gl.json b/apps/files_sharing/l10n/gl.json
index 81d97bfdcec..59355f44acf 100644
--- a/apps/files_sharing/l10n/gl.json
+++ b/apps/files_sharing/l10n/gl.json
@@ -1,9 +1,9 @@
{ "translations": {
"Server to server sharing is not enabled on this server" : "Neste servidor non está activada a compartición de servidor a servidor",
- "The mountpoint name contains invalid characters." : "O nome do punto de montaxe contén caracteres inválidos.",
+ "The mountpoint name contains invalid characters." : "O nome do punto de montaxe contén caracteres incorrectos",
"Invalid or untrusted SSL certificate" : "Certificado SSL incorrecto ou non fiábel",
- "Could not authenticate to remote share, password might be wrong" : "Non se puido autenticar na compartición remota, o contrasinal podería ser erróneo",
- "Storage not valid" : "Almacenamento non válido",
+ "Could not authenticate to remote share, password might be wrong" : "Non foi pisíbel autenticar na compartición remota, o contrasinal podería ser erróneo",
+ "Storage not valid" : "Almacenamento incorrecto",
"Couldn't add remote share" : "Non foi posíbel engadir a compartición remota",
"Shared with you" : "Compartido con vostede",
"Shared with others" : "Compartido con outros",
@@ -48,7 +48,7 @@
"Download %s" : "Descargar %s",
"Direct link" : "Ligazón directa",
"Federated Cloud Sharing" : "Compartición de nube federada",
- "Allow users on this server to send shares to other servers" : "Permitir aos ususarios de este servidor enviar comparticións a outros servidores",
- "Allow users on this server to receive shares from other servers" : "Permitir aos usuarios de este servidor recibir comparticións de outros servidores"
+ "Allow users on this server to send shares to other servers" : "Permitir aos usuarios deste servidor enviar comparticións a outros servidores",
+ "Allow users on this server to receive shares from other servers" : "Permitir aos usuarios deste servidor recibir comparticións de outros servidores"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/apps/files_sharing/l10n/ja.js b/apps/files_sharing/l10n/ja.js
index 8608d02f617..ad9481917c7 100644
--- a/apps/files_sharing/l10n/ja.js
+++ b/apps/files_sharing/l10n/ja.js
@@ -4,6 +4,7 @@ OC.L10N.register(
"Server to server sharing is not enabled on this server" : "このサーバーでは、サーバー間の共有が有効ではありません",
"The mountpoint name contains invalid characters." : "マウントポイント名 に不正な文字列が含まれています。",
"Invalid or untrusted SSL certificate" : "無効または信頼できないSSL証明書",
+ "Could not authenticate to remote share, password might be wrong" : "リモート共有が認証できませんでした,パスワードが間違っているかもしれません",
"Storage not valid" : "ストレージが無効です",
"Couldn't add remote share" : "リモート共有を追加できませんでした",
"Shared with you" : "他ユーザーがあなたと共有中",
@@ -27,6 +28,9 @@ OC.L10N.register(
"A file or folder was shared from <strong>another server</strong>" : "ファイルまたはフォルダーが<strong>他のサーバー</strong>から共有されたとき",
"A public shared file or folder was <strong>downloaded</strong>" : "公開共有ファイルまたはフォルダーが<strong>ダウンロードされた</strong>とき",
"You received a new remote share from %s" : "%sからリモート共有のリクエストは\n届きました。",
+ "%1$s accepted remote share %2$s" : "%1$s は %2$s のリモート共有を承認しました。",
+ "%1$s declined remote share %2$s" : "%1$s は %2$s のリモート共有を拒否しました。",
+ "%1$s unshared %2$s from you" : "%1$s は あなたと%2$s の共有を止めました。",
"Public shared folder %1$s was downloaded" : "公開共有フォルダ %1$s がダウンロードされました",
"Public shared file %1$s was downloaded" : "公開共有ファイル %1$s がダウンロードされました",
"This share is password-protected" : "この共有はパスワードで保護されています",
diff --git a/apps/files_sharing/l10n/ja.json b/apps/files_sharing/l10n/ja.json
index 017596b2172..44f376b4899 100644
--- a/apps/files_sharing/l10n/ja.json
+++ b/apps/files_sharing/l10n/ja.json
@@ -2,6 +2,7 @@
"Server to server sharing is not enabled on this server" : "このサーバーでは、サーバー間の共有が有効ではありません",
"The mountpoint name contains invalid characters." : "マウントポイント名 に不正な文字列が含まれています。",
"Invalid or untrusted SSL certificate" : "無効または信頼できないSSL証明書",
+ "Could not authenticate to remote share, password might be wrong" : "リモート共有が認証できませんでした,パスワードが間違っているかもしれません",
"Storage not valid" : "ストレージが無効です",
"Couldn't add remote share" : "リモート共有を追加できませんでした",
"Shared with you" : "他ユーザーがあなたと共有中",
@@ -25,6 +26,9 @@
"A file or folder was shared from <strong>another server</strong>" : "ファイルまたはフォルダーが<strong>他のサーバー</strong>から共有されたとき",
"A public shared file or folder was <strong>downloaded</strong>" : "公開共有ファイルまたはフォルダーが<strong>ダウンロードされた</strong>とき",
"You received a new remote share from %s" : "%sからリモート共有のリクエストは\n届きました。",
+ "%1$s accepted remote share %2$s" : "%1$s は %2$s のリモート共有を承認しました。",
+ "%1$s declined remote share %2$s" : "%1$s は %2$s のリモート共有を拒否しました。",
+ "%1$s unshared %2$s from you" : "%1$s は あなたと%2$s の共有を止めました。",
"Public shared folder %1$s was downloaded" : "公開共有フォルダ %1$s がダウンロードされました",
"Public shared file %1$s was downloaded" : "公開共有ファイル %1$s がダウンロードされました",
"This share is password-protected" : "この共有はパスワードで保護されています",
diff --git a/apps/files_sharing/lib/activity.php b/apps/files_sharing/lib/activity.php
index bfac91fd71a..0cd874d69f0 100644
--- a/apps/files_sharing/lib/activity.php
+++ b/apps/files_sharing/lib/activity.php
@@ -1,37 +1,70 @@
<?php
/**
- * ownCloud - publish activities
+ * ownCloud - Sharing Activity Extension
*
* @copyright (c) 2014, ownCloud Inc.
*
* @author Bjoern Schiessle <schiessle@owncloud.com>
+ * @author Joas Schilling <nickvergessen@owncloud.com>
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library 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 library. If not, see <http://www.gnu.org/licenses/>.
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
*/
namespace OCA\Files_Sharing;
-class Activity implements \OCP\Activity\IExtension {
+use OC\L10N\Factory;
+use OCP\Activity\IExtension;
+use OCP\IURLGenerator;
- const TYPE_REMOTE_SHARE = 'remote_share';
+class Activity implements IExtension {
+ /**
+ * Filter with all sharing related activities
+ */
+ const FILTER_SHARES = 'shares';
+
+ /**
+ * Activity types known to this extension
+ */
const TYPE_PUBLIC_LINKS = 'public_links';
- const SUBJECT_REMOTE_SHARE_RECEIVED = 'remote_share_received';
+ const TYPE_REMOTE_SHARE = 'remote_share';
+ const TYPE_SHARED = 'shared';
+
+ /**
+ * Subject keys for translation of the subjections
+ */
+ const SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED = 'public_shared_file_downloaded';
+ const SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED = 'public_shared_folder_downloaded';
+
const SUBJECT_REMOTE_SHARE_ACCEPTED = 'remote_share_accepted';
const SUBJECT_REMOTE_SHARE_DECLINED = 'remote_share_declined';
+ const SUBJECT_REMOTE_SHARE_RECEIVED = 'remote_share_received';
const SUBJECT_REMOTE_SHARE_UNSHARED = 'remote_share_unshared';
- const SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED = 'public_shared_file_downloaded';
- const SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED = 'public_shared_folder_downloaded';
+
+ const SUBJECT_SHARED_GROUP_SELF = 'shared_group_self';
+ const SUBJECT_SHARED_LINK_SELF = 'shared_link_self';
+ const SUBJECT_SHARED_USER_SELF = 'shared_user_self';
+ const SUBJECT_SHARED_WITH_BY = 'shared_with_by';
+
+ /** @var Factory */
+ protected $languageFactory;
+
+ /** @var IURLGenerator */
+ protected $URLGenerator;
+
+ /**
+ * @param Factory $languageFactory
+ * @param IURLGenerator $URLGenerator
+ */
+ public function __construct(Factory $languageFactory, IURLGenerator $URLGenerator) {
+ $this->languageFactory = $languageFactory;
+ $this->URLGenerator = $URLGenerator;
+ }
+
+ protected function getL10N($languageCode = null) {
+ return $this->languageFactory->get('files_sharing', $languageCode);
+ }
/**
* The extension can return an array of additional notification types.
@@ -41,45 +74,52 @@ class Activity implements \OCP\Activity\IExtension {
* @return array|false
*/
public function getNotificationTypes($languageCode) {
- $l = \OC::$server->getL10N('files_sharing', $languageCode);
+ $l = $this->getL10N($languageCode);
+
return array(
- self::TYPE_REMOTE_SHARE => $l->t('A file or folder was shared from <strong>another server</strong>'),
- self::TYPE_PUBLIC_LINKS => $l->t('A public shared file or folder was <strong>downloaded</strong>'),
+ self::TYPE_SHARED => (string) $l->t('A file or folder has been <strong>shared</strong>'),
+ self::TYPE_REMOTE_SHARE => (string) $l->t('A file or folder was shared from <strong>another server</strong>'),
+ self::TYPE_PUBLIC_LINKS => (string) $l->t('A public shared file or folder was <strong>downloaded</strong>'),
);
}
/**
- * The extension can filter the types based on the filter if required.
- * In case no filter is to be applied false is to be returned unchanged.
+ * For a given method additional types to be displayed in the settings can be returned.
+ * In case no additional types are to be added false is to be returned.
*
- * @param array $types
- * @param string $filter
+ * @param string $method
* @return array|false
*/
- public function filterNotificationTypes($types, $filter) {
- return $types;
+ public function getDefaultTypes($method) {
+ $defaultTypes = [
+ self::TYPE_SHARED,
+ self::TYPE_REMOTE_SHARE,
+ ];
+
+ if ($method === 'stream') {
+ $defaultTypes[] = self::TYPE_PUBLIC_LINKS;
+ }
+
+ return $defaultTypes;
}
/**
- * For a given method additional types to be displayed in the settings can be returned.
- * In case no additional types are to be added false is to be returned.
+ * A string naming the css class for the icon to be used can be returned.
+ * If no icon is known for the given type false is to be returned.
*
- * @param string $method
- * @return array|false
+ * @param string $type
+ * @return string|false
*/
- public function getDefaultTypes($method) {
- switch ($method) {
- case 'email':
- $result = array(self::TYPE_REMOTE_SHARE);
- break;
- case 'stream':
- $result = array(self::TYPE_REMOTE_SHARE, self::TYPE_PUBLIC_LINKS);
- break;
- default:
- $result = false;
+ public function getTypeIcon($type) {
+ switch ($type) {
+ case self::TYPE_SHARED:
+ case self::TYPE_REMOTE_SHARE:
+ return 'icon-share';
+ case self::TYPE_PUBLIC_LINKS:
+ return 'icon-download';
}
- return $result;
+ return false;
}
/**
@@ -95,23 +135,33 @@ class Activity implements \OCP\Activity\IExtension {
* @return string|false
*/
public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
-
- $l = \OC::$server->getL10N('files_sharing', $languageCode);
+ $l = $this->getL10N($languageCode);
if ($app === 'files_sharing') {
switch ($text) {
case self::SUBJECT_REMOTE_SHARE_RECEIVED:
- return $l->t('You received a new remote share from %s', $params)->__toString();
+ return (string) $l->t('You received a new remote share from %s', $params);
case self::SUBJECT_REMOTE_SHARE_ACCEPTED:
- return $l->t('%1$s accepted remote share %2$s', $params)->__toString();
+ return (string) $l->t('%1$s accepted remote share %2$s', $params);
case self::SUBJECT_REMOTE_SHARE_DECLINED:
- return $l->t('%1$s declined remote share %2$s', $params)->__toString();
+ return (string) $l->t('%1$s declined remote share %2$s', $params);
case self::SUBJECT_REMOTE_SHARE_UNSHARED:
- return $l->t('%1$s unshared %2$s from you', $params)->__toString();
+ return (string) $l->t('%1$s unshared %2$s from you', $params);
case self::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED:
- return $l->t('Public shared folder %1$s was downloaded', $params)->__toString();
+ return (string) $l->t('Public shared folder %1$s was downloaded', $params);
case self::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED:
- return $l->t('Public shared file %1$s was downloaded', $params)->__toString();
+ return (string) $l->t('Public shared file %1$s was downloaded', $params);
+ }
+ } else if ($app === 'files') {
+ switch ($text) {
+ case self::SUBJECT_SHARED_USER_SELF:
+ return (string) $l->t('You shared %1$s with %2$s', $params);
+ case self::SUBJECT_SHARED_GROUP_SELF:
+ return (string) $l->t('You shared %1$s with group %2$s', $params);
+ case self::SUBJECT_SHARED_WITH_BY:
+ return (string) $l->t('%2$s shared %1$s with you', $params);
+ case self::SUBJECT_SHARED_LINK_SELF:
+ return (string) $l->t('You shared %1$s via link', $params);
}
}
@@ -149,24 +199,19 @@ class Activity implements \OCP\Activity\IExtension {
0 => 'file',
);
}
- }
-
- return false;
- }
+ } else if ($app === 'files') {
+ switch ($text) {
+ case self::SUBJECT_SHARED_LINK_SELF:
+ case self::SUBJECT_SHARED_USER_SELF:
+ case self::SUBJECT_SHARED_WITH_BY:
+ return [0 => 'file', 1 => 'username'];
- /**
- * A string naming the css class for the icon to be used can be returned.
- * If no icon is known for the given type false is to be returned.
- *
- * @param string $type
- * @return string|false
- */
- public function getTypeIcon($type) {
- switch ($type) {
- case self::TYPE_REMOTE_SHARE:
- return 'icon-share';
- case self::TYPE_PUBLIC_LINKS:
- return 'icon-download';
+ case self::SUBJECT_SHARED_GROUP_SELF:
+ return [
+ 0 => 'file',
+ //1 => 'group', Group does not exist yet
+ ];
+ }
}
return false;
@@ -191,7 +236,17 @@ class Activity implements \OCP\Activity\IExtension {
* @return array|false
*/
public function getNavigation() {
- return false;
+ $l = $this->getL10N();
+ return [
+ 'apps' => [],
+ 'top' => [
+ self::FILTER_SHARES => [
+ 'id' => self::FILTER_SHARES,
+ 'name' => (string) $l->t('Shares'),
+ 'url' => $this->URLGenerator->linkToRoute('activity.Activities.showList', ['filter' => self::FILTER_SHARES]),
+ ],
+ ],
+ ];
}
/**
@@ -201,6 +256,22 @@ class Activity implements \OCP\Activity\IExtension {
* @return boolean
*/
public function isFilterValid($filterValue) {
+ return $filterValue === self::FILTER_SHARES;
+ }
+
+ /**
+ * The extension can filter the types based on the filter if required.
+ * In case no filter is to be applied false is to be returned unchanged.
+ *
+ * @param array $types
+ * @param string $filter
+ * @return array|false
+ */
+ public function filterNotificationTypes($types, $filter) {
+ switch ($filter) {
+ case self::FILTER_SHARES:
+ return array_intersect([self::TYPE_SHARED, self::TYPE_REMOTE_SHARE], $types);
+ }
return false;
}
@@ -214,8 +285,11 @@ class Activity implements \OCP\Activity\IExtension {
* @return array|false
*/
public function getQueryForFilter($filter) {
- if ($filter === 'shares') {
- return array('`app` = ? and `type` = ?', array('files_sharing', self::TYPE_REMOTE_SHARE));
+ if ($filter === self::FILTER_SHARES) {
+ return [
+ '(`app` = ? or `app` = ?)',
+ ['files_sharing', 'files'],
+ ];
}
return false;
}
diff --git a/apps/files_sharing/lib/controllers/sharecontroller.php b/apps/files_sharing/lib/controllers/sharecontroller.php
index 34339154b5c..cdcf3bbdc37 100644
--- a/apps/files_sharing/lib/controllers/sharecontroller.php
+++ b/apps/files_sharing/lib/controllers/sharecontroller.php
@@ -230,26 +230,48 @@ class ShareController extends Controller {
}
}
+ $files_list = null;
+ if (!is_null($files)) { // download selected files
+ $files_list = json_decode($files);
+ // in case we get only a single file
+ if ($files_list === null) {
+ $files_list = array($files);
+ }
+ }
+
$originalSharePath = self::getPath($token);
+ // Create the activities
if (isset($originalSharePath) && Filesystem::isReadable($originalSharePath . $path)) {
$originalSharePath = Filesystem::normalizePath($originalSharePath . $path);
- $type = \OC\Files\Filesystem::is_dir($originalSharePath) ? 'folder' : 'file';
- $args = $type === 'folder' ? array('dir' => $originalSharePath) : array('dir' => dirname($originalSharePath), 'scrollto' => basename($originalSharePath));
- $linkToFile = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
- $subject = $type === 'folder' ? Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED : Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
- $this->activityManager->publishActivity(
- 'files_sharing', $subject, array($originalSharePath), '', array(), $originalSharePath,
- $linkToFile, $linkItem['uid_owner'], Activity::TYPE_PUBLIC_LINKS, Activity::PRIORITY_MEDIUM);
- }
+ $isDir = \OC\Files\Filesystem::is_dir($originalSharePath);
- if (!is_null($files)) { // download selected files
- $files_list = json_decode($files);
- // in case we get only a single file
- if ($files_list === NULL) {
- $files_list = array($files);
+ $activities = [];
+ if (!$isDir) {
+ // Single file public share
+ $activities[$originalSharePath] = Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
+ } else if (!empty($files_list)) {
+ // Only some files are downloaded
+ foreach ($files_list as $file) {
+ $filePath = Filesystem::normalizePath($originalSharePath . '/' . $file);
+ $isDir = \OC\Files\Filesystem::is_dir($filePath);
+ $activities[$filePath] = ($isDir) ? Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED : Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
+ }
+ } else {
+ // The folder is downloaded
+ $activities[$originalSharePath] = Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
}
+ foreach ($activities as $filePath => $subject) {
+ $this->activityManager->publishActivity(
+ 'files_sharing', $subject, array($filePath), '', array(),
+ $filePath, '', $linkItem['uid_owner'], Activity::TYPE_PUBLIC_LINKS, Activity::PRIORITY_MEDIUM
+ );
+ }
+ }
+
+ // download selected files
+ if (!is_null($files)) {
// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
// after dispatching the request which results in a "Cannot modify header information" notice.
OC_Files::get($originalSharePath, $files_list, $_SERVER['REQUEST_METHOD'] == 'HEAD');
diff --git a/apps/files_sharing/tests/activity.php b/apps/files_sharing/tests/activity.php
index 04930e3bb76..6975a41fb8b 100644
--- a/apps/files_sharing/tests/activity.php
+++ b/apps/files_sharing/tests/activity.php
@@ -34,7 +34,12 @@ class Activity extends \OCA\Files_Sharing\Tests\TestCase{
protected function setUp() {
parent::setUp();
- $this->activity = new \OCA\Files_Sharing\Activity();
+ $this->activity = new \OCA\Files_Sharing\Activity(
+ $this->getMock('\OC\L10N\Factory'),
+ $this->getMockBuilder('\OC\URLGenerator')
+ ->disableOriginalConstructor()
+ ->getMock()
+ );
}
/**
@@ -56,9 +61,8 @@ class Activity extends \OCA\Files_Sharing\Tests\TestCase{
public function dataTestGetDefaultType() {
return array(
- array('email', array(\OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE)),
- array('stream', array(\OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::TYPE_PUBLIC_LINKS)),
- array('foo', false)
+ array('email', array(\OCA\Files_Sharing\Activity::TYPE_SHARED, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE)),
+ array('stream', array(\OCA\Files_Sharing\Activity::TYPE_SHARED, \OCA\Files_Sharing\Activity::TYPE_REMOTE_SHARE, \OCA\Files_Sharing\Activity::TYPE_PUBLIC_LINKS)),
);
}
diff --git a/apps/user_ldap/l10n/de.js b/apps/user_ldap/l10n/de.js
index ba6d9c214f3..2dab70d34af 100644
--- a/apps/user_ldap/l10n/de.js
+++ b/apps/user_ldap/l10n/de.js
@@ -1,10 +1,10 @@
OC.L10N.register(
"user_ldap",
{
- "Failed to clear the mappings." : "Löschen der Zuordnung fehlgeschlagen.",
+ "Failed to clear the mappings." : "Löschen der Zuordnungen fehlgeschlagen.",
"Failed to delete the server configuration" : "Löschen der Serverkonfiguration fehlgeschlagen",
"The configuration is valid and the connection could be established!" : "Die Konfiguration ist gültig und die Verbindung konnte hergestellt werden!",
- "The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "Die Konfiguration ist gültig aber die Verbindung ist fehlgeschlagen. Bitte überprüfe die Servereinstellungen und Anmeldeinformationen.",
+ "The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "Die Konfiguration ist gültig, aber die Verbindung ist fehlgeschlagen. Bitte überprüfe die Servereinstellungen und Anmeldeinformationen.",
"The configuration is invalid. Please have a look at the logs for further details." : "Die Konfiguration ist ungültig. Weitere Details kannst Du in den Logdateien nachlesen.",
"No action specified" : "Keine Aktion spezifiziert",
"No configuration specified" : "Keine Konfiguration spezifiziert",
@@ -18,7 +18,7 @@ OC.L10N.register(
"mappings cleared" : "Zuordnungen gelöscht",
"Success" : "Erfolgreich",
"Error" : "Fehler",
- "Please specify a Base DN" : "Bitte ein Base-DN spezifizieren",
+ "Please specify a Base DN" : "Bitte einen Base-DN angeben",
"Could not determine Base DN" : "Base-DN konnte nicht festgestellt werden",
"Please specify the port" : "Bitte Port spezifizieren",
"Configuration OK" : "Konfiguration OK",
@@ -48,12 +48,12 @@ OC.L10N.register(
"only from those groups:" : "Nur von diesen Gruppen:",
"Edit raw filter instead" : "Original-Filter stattdessen bearbeiten",
"Raw LDAP filter" : "Original LDAP-Filter",
- "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter definiert welche LDAP-Gruppen Zugriff auf die %s Instanz haben sollen.",
+ "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter bestimmt, welche LDAP-Gruppen Zugriff auf die %s-Instanz haben sollen.",
"Test Filter" : "Test-Filter",
"groups found" : "Gruppen gefunden",
"Users login with this attribute:" : "Nutzeranmeldung mit diesem Merkmal:",
"LDAP Username:" : "LDAP-Benutzername:",
- "LDAP Email Address:" : "LDAP E-Mail-Adresse:",
+ "LDAP Email Address:" : "LDAP-E-Mail-Adresse:",
"Other Attributes:" : "Andere Attribute:",
"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Bestimmt den Filter, welcher bei einer Anmeldung angewandt wird. %%uid ersetzt den Benutzernamen bei der Anmeldung. Beispiel: \"uid=%%uid\"",
"1. Server" : "1. Server",
@@ -67,7 +67,7 @@ OC.L10N.register(
"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." : "Der DN des Benutzers für LDAP-Bind, z.B.: uid=agent,dc=example,dc=com. Für anonymen Zugriff lasse DN und Passwort leer.",
"Password" : "Passwort",
"For anonymous access, leave DN and Password empty." : "Lasse die Felder DN und Passwort für anonymen Zugang leer.",
- "One Base DN per line" : "Ein Basis-DN pro Zeile",
+ "One Base DN per line" : "Einen Basis-DN pro Zeile",
"You can specify Base DN for users and groups in the Advanced tab" : "Du kannst Basis-DN für Benutzer und Gruppen in dem \"Erweitert\"-Reiter konfigurieren",
"Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge." : "Verhindert automatische LDAP-Anfragen. Besser für größere Installationen, benötigt aber einiges an LDAP-Wissen.",
"Manually enter LDAP filters (recommended for large directories)" : "LDAP-Filter manuell eingeben (erforderlich für große Verzeichnisse)",
diff --git a/apps/user_ldap/l10n/de.json b/apps/user_ldap/l10n/de.json
index df4af011afc..b31dbbf38a7 100644
--- a/apps/user_ldap/l10n/de.json
+++ b/apps/user_ldap/l10n/de.json
@@ -1,8 +1,8 @@
{ "translations": {
- "Failed to clear the mappings." : "Löschen der Zuordnung fehlgeschlagen.",
+ "Failed to clear the mappings." : "Löschen der Zuordnungen fehlgeschlagen.",
"Failed to delete the server configuration" : "Löschen der Serverkonfiguration fehlgeschlagen",
"The configuration is valid and the connection could be established!" : "Die Konfiguration ist gültig und die Verbindung konnte hergestellt werden!",
- "The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "Die Konfiguration ist gültig aber die Verbindung ist fehlgeschlagen. Bitte überprüfe die Servereinstellungen und Anmeldeinformationen.",
+ "The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "Die Konfiguration ist gültig, aber die Verbindung ist fehlgeschlagen. Bitte überprüfe die Servereinstellungen und Anmeldeinformationen.",
"The configuration is invalid. Please have a look at the logs for further details." : "Die Konfiguration ist ungültig. Weitere Details kannst Du in den Logdateien nachlesen.",
"No action specified" : "Keine Aktion spezifiziert",
"No configuration specified" : "Keine Konfiguration spezifiziert",
@@ -16,7 +16,7 @@
"mappings cleared" : "Zuordnungen gelöscht",
"Success" : "Erfolgreich",
"Error" : "Fehler",
- "Please specify a Base DN" : "Bitte ein Base-DN spezifizieren",
+ "Please specify a Base DN" : "Bitte einen Base-DN angeben",
"Could not determine Base DN" : "Base-DN konnte nicht festgestellt werden",
"Please specify the port" : "Bitte Port spezifizieren",
"Configuration OK" : "Konfiguration OK",
@@ -46,12 +46,12 @@
"only from those groups:" : "Nur von diesen Gruppen:",
"Edit raw filter instead" : "Original-Filter stattdessen bearbeiten",
"Raw LDAP filter" : "Original LDAP-Filter",
- "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter definiert welche LDAP-Gruppen Zugriff auf die %s Instanz haben sollen.",
+ "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter bestimmt, welche LDAP-Gruppen Zugriff auf die %s-Instanz haben sollen.",
"Test Filter" : "Test-Filter",
"groups found" : "Gruppen gefunden",
"Users login with this attribute:" : "Nutzeranmeldung mit diesem Merkmal:",
"LDAP Username:" : "LDAP-Benutzername:",
- "LDAP Email Address:" : "LDAP E-Mail-Adresse:",
+ "LDAP Email Address:" : "LDAP-E-Mail-Adresse:",
"Other Attributes:" : "Andere Attribute:",
"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Bestimmt den Filter, welcher bei einer Anmeldung angewandt wird. %%uid ersetzt den Benutzernamen bei der Anmeldung. Beispiel: \"uid=%%uid\"",
"1. Server" : "1. Server",
@@ -65,7 +65,7 @@
"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." : "Der DN des Benutzers für LDAP-Bind, z.B.: uid=agent,dc=example,dc=com. Für anonymen Zugriff lasse DN und Passwort leer.",
"Password" : "Passwort",
"For anonymous access, leave DN and Password empty." : "Lasse die Felder DN und Passwort für anonymen Zugang leer.",
- "One Base DN per line" : "Ein Basis-DN pro Zeile",
+ "One Base DN per line" : "Einen Basis-DN pro Zeile",
"You can specify Base DN for users and groups in the Advanced tab" : "Du kannst Basis-DN für Benutzer und Gruppen in dem \"Erweitert\"-Reiter konfigurieren",
"Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge." : "Verhindert automatische LDAP-Anfragen. Besser für größere Installationen, benötigt aber einiges an LDAP-Wissen.",
"Manually enter LDAP filters (recommended for large directories)" : "LDAP-Filter manuell eingeben (erforderlich für große Verzeichnisse)",
diff --git a/apps/user_ldap/l10n/de_DE.js b/apps/user_ldap/l10n/de_DE.js
index 692751d0451..2e7ce537284 100644
--- a/apps/user_ldap/l10n/de_DE.js
+++ b/apps/user_ldap/l10n/de_DE.js
@@ -1,7 +1,7 @@
OC.L10N.register(
"user_ldap",
{
- "Failed to clear the mappings." : "Löschen der Zuordnung fehlgeschlagen.",
+ "Failed to clear the mappings." : "Löschen der Zuordnungen fehlgeschlagen.",
"Failed to delete the server configuration" : "Löschen der Serverkonfiguration fehlgeschlagen",
"The configuration is valid and the connection could be established!" : "Die Konfiguration ist gültig und die Verbindung konnte hergestellt werden!",
"The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "Die Konfiguration ist gültig, aber die Verbindung ist fehlgeschlagen. Bitte überprüfen Sie die Servereinstellungen und die Anmeldeinformationen.",
@@ -18,7 +18,7 @@ OC.L10N.register(
"mappings cleared" : "Zuordnungen gelöscht",
"Success" : "Erfolg",
"Error" : "Fehler",
- "Please specify a Base DN" : "Bitte ein Base-DN spezifizieren",
+ "Please specify a Base DN" : "Bitte einen Base-DN angeben",
"Could not determine Base DN" : "Base-DN konnte nicht festgestellt werden",
"Please specify the port" : "Bitte Port spezifizieren",
"Configuration OK" : "Konfiguration OK",
@@ -48,12 +48,12 @@ OC.L10N.register(
"only from those groups:" : "Nur von diesen Gruppen:",
"Edit raw filter instead" : "Original-Filter stattdessen bearbeiten",
"Raw LDAP filter" : "Original LDAP-Filter",
- "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter definiert welche LDAP-Gruppen Zugriff auf die %s Instanz haben sollen.",
+ "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter bestimmt, welche LDAP-Gruppen Zugriff auf die %s-Instanz haben sollen.",
"Test Filter" : "Test-Filter",
"groups found" : "Gruppen gefunden",
"Users login with this attribute:" : "Benutzeranmeldung mit diesem Merkmal:",
"LDAP Username:" : "LDAP-Benutzername:",
- "LDAP Email Address:" : "LDAP E-Mail-Adresse:",
+ "LDAP Email Address:" : "LDAP-E-Mail-Adresse:",
"Other Attributes:" : "Andere Attribute:",
"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Bestimmt den Filter, welcher bei einer Anmeldung angewandt wird. %%uid ersetzt den Benutzernamen bei der Anmeldung. Beispiel: \"uid=%%uid\"",
"1. Server" : "1. Server",
@@ -67,7 +67,7 @@ OC.L10N.register(
"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." : "Der DN des Benutzers für LDAP-Bind, z.B.: uid=agent,dc=example,dc=com. Für einen anonymen Zugriff lassen Sie DN und Passwort leer.",
"Password" : "Passwort",
"For anonymous access, leave DN and Password empty." : "Lassen Sie die Felder DN und Passwort für einen anonymen Zugang leer.",
- "One Base DN per line" : "Ein Basis-DN pro Zeile",
+ "One Base DN per line" : "Einen Basis-DN pro Zeile",
"You can specify Base DN for users and groups in the Advanced tab" : "Sie können Basis-DN für Benutzer und Gruppen in dem \"Erweitert\"-Reiter konfigurieren",
"Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge." : "Verhindert automatische LDAP-Anfragen. Besser für größere Installationen, benötigt aber einiges an LDAP-Wissen.",
"Manually enter LDAP filters (recommended for large directories)" : "LDAP-Filter manuell eingeben (erforderlich für große Verzeichnisse)",
diff --git a/apps/user_ldap/l10n/de_DE.json b/apps/user_ldap/l10n/de_DE.json
index 1b8b3d4cea2..d847911a7bd 100644
--- a/apps/user_ldap/l10n/de_DE.json
+++ b/apps/user_ldap/l10n/de_DE.json
@@ -1,5 +1,5 @@
{ "translations": {
- "Failed to clear the mappings." : "Löschen der Zuordnung fehlgeschlagen.",
+ "Failed to clear the mappings." : "Löschen der Zuordnungen fehlgeschlagen.",
"Failed to delete the server configuration" : "Löschen der Serverkonfiguration fehlgeschlagen",
"The configuration is valid and the connection could be established!" : "Die Konfiguration ist gültig und die Verbindung konnte hergestellt werden!",
"The configuration is valid, but the Bind failed. Please check the server settings and credentials." : "Die Konfiguration ist gültig, aber die Verbindung ist fehlgeschlagen. Bitte überprüfen Sie die Servereinstellungen und die Anmeldeinformationen.",
@@ -16,7 +16,7 @@
"mappings cleared" : "Zuordnungen gelöscht",
"Success" : "Erfolg",
"Error" : "Fehler",
- "Please specify a Base DN" : "Bitte ein Base-DN spezifizieren",
+ "Please specify a Base DN" : "Bitte einen Base-DN angeben",
"Could not determine Base DN" : "Base-DN konnte nicht festgestellt werden",
"Please specify the port" : "Bitte Port spezifizieren",
"Configuration OK" : "Konfiguration OK",
@@ -46,12 +46,12 @@
"only from those groups:" : "Nur von diesen Gruppen:",
"Edit raw filter instead" : "Original-Filter stattdessen bearbeiten",
"Raw LDAP filter" : "Original LDAP-Filter",
- "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter definiert welche LDAP-Gruppen Zugriff auf die %s Instanz haben sollen.",
+ "The filter specifies which LDAP groups shall have access to the %s instance." : "Der Filter bestimmt, welche LDAP-Gruppen Zugriff auf die %s-Instanz haben sollen.",
"Test Filter" : "Test-Filter",
"groups found" : "Gruppen gefunden",
"Users login with this attribute:" : "Benutzeranmeldung mit diesem Merkmal:",
"LDAP Username:" : "LDAP-Benutzername:",
- "LDAP Email Address:" : "LDAP E-Mail-Adresse:",
+ "LDAP Email Address:" : "LDAP-E-Mail-Adresse:",
"Other Attributes:" : "Andere Attribute:",
"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Bestimmt den Filter, welcher bei einer Anmeldung angewandt wird. %%uid ersetzt den Benutzernamen bei der Anmeldung. Beispiel: \"uid=%%uid\"",
"1. Server" : "1. Server",
@@ -65,7 +65,7 @@
"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." : "Der DN des Benutzers für LDAP-Bind, z.B.: uid=agent,dc=example,dc=com. Für einen anonymen Zugriff lassen Sie DN und Passwort leer.",
"Password" : "Passwort",
"For anonymous access, leave DN and Password empty." : "Lassen Sie die Felder DN und Passwort für einen anonymen Zugang leer.",
- "One Base DN per line" : "Ein Basis-DN pro Zeile",
+ "One Base DN per line" : "Einen Basis-DN pro Zeile",
"You can specify Base DN for users and groups in the Advanced tab" : "Sie können Basis-DN für Benutzer und Gruppen in dem \"Erweitert\"-Reiter konfigurieren",
"Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge." : "Verhindert automatische LDAP-Anfragen. Besser für größere Installationen, benötigt aber einiges an LDAP-Wissen.",
"Manually enter LDAP filters (recommended for large directories)" : "LDAP-Filter manuell eingeben (erforderlich für große Verzeichnisse)",
diff --git a/apps/user_ldap/l10n/gl.js b/apps/user_ldap/l10n/gl.js
index a2359d41ebc..246e9950b3d 100644
--- a/apps/user_ldap/l10n/gl.js
+++ b/apps/user_ldap/l10n/gl.js
@@ -20,7 +20,7 @@ OC.L10N.register(
"Error" : "Erro",
"Please specify a Base DN" : "Por favor indique un DN base",
"Could not determine Base DN" : "Non se puido determinar o DN base",
- "Please specify the port" : "Por favor indique un porto",
+ "Please specify the port" : "Especifique un porto",
"Configuration OK" : "Configuración correcta",
"Configuration incorrect" : "Configuración incorrecta",
"Configuration incomplete" : "Configuración incompleta",
diff --git a/apps/user_ldap/l10n/gl.json b/apps/user_ldap/l10n/gl.json
index 0f6d4e00cdf..9e8fceaa250 100644
--- a/apps/user_ldap/l10n/gl.json
+++ b/apps/user_ldap/l10n/gl.json
@@ -18,7 +18,7 @@
"Error" : "Erro",
"Please specify a Base DN" : "Por favor indique un DN base",
"Could not determine Base DN" : "Non se puido determinar o DN base",
- "Please specify the port" : "Por favor indique un porto",
+ "Please specify the port" : "Especifique un porto",
"Configuration OK" : "Configuración correcta",
"Configuration incorrect" : "Configuración incorrecta",
"Configuration incomplete" : "Configuración incompleta",
diff --git a/apps/user_ldap/l10n/mr.js b/apps/user_ldap/l10n/mr.js
new file mode 100644
index 00000000000..37042a4f412
--- /dev/null
+++ b/apps/user_ldap/l10n/mr.js
@@ -0,0 +1,7 @@
+OC.L10N.register(
+ "user_ldap",
+ {
+ "_%s group found_::_%s groups found_" : ["",""],
+ "_%s user found_::_%s users found_" : ["",""]
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/user_ldap/l10n/mr.json b/apps/user_ldap/l10n/mr.json
new file mode 100644
index 00000000000..521de7ba1a8
--- /dev/null
+++ b/apps/user_ldap/l10n/mr.json
@@ -0,0 +1,5 @@
+{ "translations": {
+ "_%s group found_::_%s groups found_" : ["",""],
+ "_%s user found_::_%s users found_" : ["",""]
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/user_webdavauth/l10n/de.js b/apps/user_webdavauth/l10n/de.js
index aead50e2b72..6e667dca0b7 100644
--- a/apps/user_webdavauth/l10n/de.js
+++ b/apps/user_webdavauth/l10n/de.js
@@ -1,7 +1,7 @@
OC.L10N.register(
"user_webdavauth",
{
- "WebDAV Authentication" : "WebDAV Authentifikation",
+ "WebDAV Authentication" : "WebDAV-Authentifizierung",
"Address:" : "Adresse:",
"Save" : "Speichern",
"The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials." : "Die Benutzerdaten werden an diese Adresse gesendet. Dieses Plugin prüft die Antwort und wird die HTTP-Statuscodes 401 und 403 als ungültige Daten interpretieren und alle anderen Antworten als gültige Daten."
diff --git a/apps/user_webdavauth/l10n/de.json b/apps/user_webdavauth/l10n/de.json
index 6a9a9520dce..f347f7724e5 100644
--- a/apps/user_webdavauth/l10n/de.json
+++ b/apps/user_webdavauth/l10n/de.json
@@ -1,5 +1,5 @@
{ "translations": {
- "WebDAV Authentication" : "WebDAV Authentifikation",
+ "WebDAV Authentication" : "WebDAV-Authentifizierung",
"Address:" : "Adresse:",
"Save" : "Speichern",
"The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials." : "Die Benutzerdaten werden an diese Adresse gesendet. Dieses Plugin prüft die Antwort und wird die HTTP-Statuscodes 401 und 403 als ungültige Daten interpretieren und alle anderen Antworten als gültige Daten."