summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Pflug <dev@admin4.org>2017-01-31 02:27:29 +0100
committerAndreas Pflug <dev@admin4.org>2017-01-31 02:27:29 +0100
commit07b203d12ffda9c6a92e374272d5c188855520a3 (patch)
tree56317aad08549c0c911f7b41e3772960086aee71
parentb64e48335f63662a43d0b7198fd013d4af521996 (diff)
parente50320dc71135bf546c757f7dea6e23f5f48a906 (diff)
downloadnextcloud-server-07b203d12ffda9c6a92e374272d5c188855520a3.tar.gz
nextcloud-server-07b203d12ffda9c6a92e374272d5c188855520a3.zip
Merge branch 'master' of https://github.com/nextcloud/server into ldap_no-memberof-with-memberuid
m---------3rdparty0
-rw-r--r--apps/federation/l10n/lv.js2
-rw-r--r--apps/federation/l10n/lv.json2
-rw-r--r--apps/files/l10n/lv.js1
-rw-r--r--apps/files/l10n/lv.json1
-rw-r--r--apps/files_external/3rdparty/composer/autoload_classmap.php4
-rw-r--r--apps/files_external/3rdparty/composer/autoload_static.php4
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Change.php40
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/Exception/DependencyException.php11
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php46
-rw-r--r--apps/files_external/3rdparty/icewind/smb/src/NotifyHandler.php88
-rw-r--r--apps/files_external/l10n/zh_CN.js81
-rw-r--r--apps/files_external/l10n/zh_CN.json81
-rw-r--r--apps/files_external/lib/Command/Notify.php57
-rw-r--r--apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php150
-rw-r--r--apps/files_external/lib/Lib/Storage/SFTP.php2
-rw-r--r--apps/files_external/lib/Lib/Storage/SMB.php51
-rw-r--r--apps/files_external/tests/Storage/SmbTest.php47
-rw-r--r--apps/files_trashbin/lib/Trashbin.php2
-rw-r--r--apps/theming/lib/Util.php2
-rw-r--r--apps/twofactor_backupcodes/l10n/lv.js2
-rw-r--r--apps/twofactor_backupcodes/l10n/lv.json2
-rw-r--r--core/css/apps.scss42
-rw-r--r--core/css/header.scss38
-rw-r--r--core/l10n/zh_CN.js10
-rw-r--r--core/l10n/zh_CN.json10
-rw-r--r--lib/composer/composer/autoload_classmap.php5
-rw-r--r--lib/composer/composer/autoload_static.php5
-rw-r--r--lib/l10n/zh_CN.js63
-rw-r--r--lib/l10n/zh_CN.json63
-rw-r--r--lib/private/Files/Notify/Change.php65
-rw-r--r--lib/private/Files/Notify/RenameChange.php52
-rw-r--r--lib/private/Files/Storage/Local.php13
-rw-r--r--lib/private/Repair/MoveUpdaterStepFile.php2
-rw-r--r--lib/private/Setup/Sqlite.php2
-rw-r--r--lib/private/User/User.php2
-rw-r--r--lib/public/Files/Notify/IChange.php56
-rw-r--r--lib/public/Files/Notify/INotifyHandler.php64
-rw-r--r--lib/public/Files/Notify/IRenameChange.php40
-rw-r--r--lib/public/Files/Storage/INotifyStorage.php13
-rw-r--r--settings/l10n/sv.js2
-rw-r--r--settings/l10n/sv.json2
-rw-r--r--settings/l10n/zh_CN.js2
-rw-r--r--settings/l10n/zh_CN.json2
44 files changed, 1037 insertions, 192 deletions
diff --git a/3rdparty b/3rdparty
-Subproject f2d8ba7bfebb769835b637f01eaa602e36cdcca
+Subproject 489bcf4f81e462f4d74f0b76f58caeabd58e75d
diff --git a/apps/federation/l10n/lv.js b/apps/federation/l10n/lv.js
index 8ceb8c09f16..ebb8c434086 100644
--- a/apps/federation/l10n/lv.js
+++ b/apps/federation/l10n/lv.js
@@ -4,7 +4,9 @@ OC.L10N.register(
"Added to the list of trusted servers" : "Sarakstam pievieno uzticamo serveri",
"Server is already in the list of trusted servers." : "Serveris jau ir uzticamo serveru sarakstā .",
"No server to federate with found" : "Nav atrasts neviens serveris",
+ "Could not add server" : "Nevarēja pievienot serveri",
"Federation" : "Federācija",
+ "Federation allows you to connect with other trusted servers to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "Federācija ļauj savienot ar citiem uzticamiem serveriem ar Exchange lietotāja direktoriju. Piemēram, tas tiks izmantots, lai automātiski pieslēgtu ārējiem lietotājiem integrēto koplietošanu.",
"Trusted servers" : "Uzticami serveri",
"+ Add trusted server" : "+ pievietot uzticamiem serveriem",
"Trusted server" : "Uzticams serveris",
diff --git a/apps/federation/l10n/lv.json b/apps/federation/l10n/lv.json
index 14dbab413d5..0a175e09e02 100644
--- a/apps/federation/l10n/lv.json
+++ b/apps/federation/l10n/lv.json
@@ -2,7 +2,9 @@
"Added to the list of trusted servers" : "Sarakstam pievieno uzticamo serveri",
"Server is already in the list of trusted servers." : "Serveris jau ir uzticamo serveru sarakstā .",
"No server to federate with found" : "Nav atrasts neviens serveris",
+ "Could not add server" : "Nevarēja pievienot serveri",
"Federation" : "Federācija",
+ "Federation allows you to connect with other trusted servers to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "Federācija ļauj savienot ar citiem uzticamiem serveriem ar Exchange lietotāja direktoriju. Piemēram, tas tiks izmantots, lai automātiski pieslēgtu ārējiem lietotājiem integrēto koplietošanu.",
"Trusted servers" : "Uzticami serveri",
"+ Add trusted server" : "+ pievietot uzticamiem serveriem",
"Trusted server" : "Uzticams serveris",
diff --git a/apps/files/l10n/lv.js b/apps/files/l10n/lv.js
index 64db0c754a8..7a86ef07b5e 100644
--- a/apps/files/l10n/lv.js
+++ b/apps/files/l10n/lv.js
@@ -14,6 +14,7 @@ OC.L10N.register(
"Upload cancelled." : "Augšupielāde ir atcelta.",
"Unable to upload {filename} as it is a directory or has 0 bytes" : "Neizdodas augšupielādēt {filename}, jo tā ir vai nu mape vai 0 baitu saturoša datne.",
"Not enough free space, you are uploading {size1} but only {size2} is left" : "Nav pietiekami daudz brīvas vietas. Tiek augšupielādēti {size1}, bet pieejami tikai {size2}",
+ "Target folder \"{dir}\" does not exist any more" : "Mape \"{dir}\" vairs neeksistē",
"Not enough free space" : "Nav pietiekami daudz brīvas vietas",
"Uploading..." : "Augšupielādē...",
"..." : "...",
diff --git a/apps/files/l10n/lv.json b/apps/files/l10n/lv.json
index 1ef5db26718..fe675e6d1fc 100644
--- a/apps/files/l10n/lv.json
+++ b/apps/files/l10n/lv.json
@@ -12,6 +12,7 @@
"Upload cancelled." : "Augšupielāde ir atcelta.",
"Unable to upload {filename} as it is a directory or has 0 bytes" : "Neizdodas augšupielādēt {filename}, jo tā ir vai nu mape vai 0 baitu saturoša datne.",
"Not enough free space, you are uploading {size1} but only {size2} is left" : "Nav pietiekami daudz brīvas vietas. Tiek augšupielādēti {size1}, bet pieejami tikai {size2}",
+ "Target folder \"{dir}\" does not exist any more" : "Mape \"{dir}\" vairs neeksistē",
"Not enough free space" : "Nav pietiekami daudz brīvas vietas",
"Uploading..." : "Augšupielādē...",
"..." : "...",
diff --git a/apps/files_external/3rdparty/composer/autoload_classmap.php b/apps/files_external/3rdparty/composer/autoload_classmap.php
index e6bba3a9a15..97f4ce99cda 100644
--- a/apps/files_external/3rdparty/composer/autoload_classmap.php
+++ b/apps/files_external/3rdparty/composer/autoload_classmap.php
@@ -7,6 +7,7 @@ $baseDir = $vendorDir;
return array(
'Icewind\\SMB\\AbstractShare' => $vendorDir . '/icewind/smb/src/AbstractShare.php',
+ 'Icewind\\SMB\\Change' => $vendorDir . '/icewind/smb/src/Change.php',
'Icewind\\SMB\\Connection' => $vendorDir . '/icewind/smb/src/Connection.php',
'Icewind\\SMB\\ErrorCodes' => $vendorDir . '/icewind/smb/src/ErrorCodes.php',
'Icewind\\SMB\\Exception\\AccessDeniedException' => $vendorDir . '/icewind/smb/src/Exception/AccessDeniedException.php',
@@ -15,6 +16,7 @@ return array(
'Icewind\\SMB\\Exception\\ConnectException' => $vendorDir . '/icewind/smb/src/Exception/ConnectException.php',
'Icewind\\SMB\\Exception\\ConnectionException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionException.php',
'Icewind\\SMB\\Exception\\ConnectionRefusedException' => $vendorDir . '/icewind/smb/src/Exception/ConnectionRefusedException.php',
+ 'Icewind\\SMB\\Exception\\DependencyException' => $vendorDir . '/icewind/smb/src/Exception/DependencyException.php',
'Icewind\\SMB\\Exception\\Exception' => $vendorDir . '/icewind/smb/src/Exception/Exception.php',
'Icewind\\SMB\\Exception\\FileInUseException' => $vendorDir . '/icewind/smb/src/Exception/FileInUseException.php',
'Icewind\\SMB\\Exception\\ForbiddenException' => $vendorDir . '/icewind/smb/src/Exception/ForbiddenException.php',
@@ -31,12 +33,14 @@ return array(
'Icewind\\SMB\\Exception\\TimedOutException' => $vendorDir . '/icewind/smb/src/Exception/TimedOutException.php',
'Icewind\\SMB\\FileInfo' => $vendorDir . '/icewind/smb/src/FileInfo.php',
'Icewind\\SMB\\IFileInfo' => $vendorDir . '/icewind/smb/src/IFileInfo.php',
+ 'Icewind\\SMB\\INotifyHandler' => $vendorDir . '/icewind/smb/src/INotifyHandler.php',
'Icewind\\SMB\\IShare' => $vendorDir . '/icewind/smb/src/IShare.php',
'Icewind\\SMB\\NativeFileInfo' => $vendorDir . '/icewind/smb/src/NativeFileInfo.php',
'Icewind\\SMB\\NativeServer' => $vendorDir . '/icewind/smb/src/NativeServer.php',
'Icewind\\SMB\\NativeShare' => $vendorDir . '/icewind/smb/src/NativeShare.php',
'Icewind\\SMB\\NativeState' => $vendorDir . '/icewind/smb/src/NativeState.php',
'Icewind\\SMB\\NativeStream' => $vendorDir . '/icewind/smb/src/NativeStream.php',
+ 'Icewind\\SMB\\NotifyHandler' => $vendorDir . '/icewind/smb/src/NotifyHandler.php',
'Icewind\\SMB\\Parser' => $vendorDir . '/icewind/smb/src/Parser.php',
'Icewind\\SMB\\RawConnection' => $vendorDir . '/icewind/smb/src/RawConnection.php',
'Icewind\\SMB\\Server' => $vendorDir . '/icewind/smb/src/Server.php',
diff --git a/apps/files_external/3rdparty/composer/autoload_static.php b/apps/files_external/3rdparty/composer/autoload_static.php
index 9fa922caeab..c1a3a0492d0 100644
--- a/apps/files_external/3rdparty/composer/autoload_static.php
+++ b/apps/files_external/3rdparty/composer/autoload_static.php
@@ -37,6 +37,7 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3
public static $classMap = array (
'Icewind\\SMB\\AbstractShare' => __DIR__ . '/..' . '/icewind/smb/src/AbstractShare.php',
+ 'Icewind\\SMB\\Change' => __DIR__ . '/..' . '/icewind/smb/src/Change.php',
'Icewind\\SMB\\Connection' => __DIR__ . '/..' . '/icewind/smb/src/Connection.php',
'Icewind\\SMB\\ErrorCodes' => __DIR__ . '/..' . '/icewind/smb/src/ErrorCodes.php',
'Icewind\\SMB\\Exception\\AccessDeniedException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/AccessDeniedException.php',
@@ -45,6 +46,7 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3
'Icewind\\SMB\\Exception\\ConnectException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectException.php',
'Icewind\\SMB\\Exception\\ConnectionException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectionException.php',
'Icewind\\SMB\\Exception\\ConnectionRefusedException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ConnectionRefusedException.php',
+ 'Icewind\\SMB\\Exception\\DependencyException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/DependencyException.php',
'Icewind\\SMB\\Exception\\Exception' => __DIR__ . '/..' . '/icewind/smb/src/Exception/Exception.php',
'Icewind\\SMB\\Exception\\FileInUseException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/FileInUseException.php',
'Icewind\\SMB\\Exception\\ForbiddenException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/ForbiddenException.php',
@@ -61,12 +63,14 @@ class ComposerStaticInit98fe9b281934250b3a93f69a5ce843b3
'Icewind\\SMB\\Exception\\TimedOutException' => __DIR__ . '/..' . '/icewind/smb/src/Exception/TimedOutException.php',
'Icewind\\SMB\\FileInfo' => __DIR__ . '/..' . '/icewind/smb/src/FileInfo.php',
'Icewind\\SMB\\IFileInfo' => __DIR__ . '/..' . '/icewind/smb/src/IFileInfo.php',
+ 'Icewind\\SMB\\INotifyHandler' => __DIR__ . '/..' . '/icewind/smb/src/INotifyHandler.php',
'Icewind\\SMB\\IShare' => __DIR__ . '/..' . '/icewind/smb/src/IShare.php',
'Icewind\\SMB\\NativeFileInfo' => __DIR__ . '/..' . '/icewind/smb/src/NativeFileInfo.php',
'Icewind\\SMB\\NativeServer' => __DIR__ . '/..' . '/icewind/smb/src/NativeServer.php',
'Icewind\\SMB\\NativeShare' => __DIR__ . '/..' . '/icewind/smb/src/NativeShare.php',
'Icewind\\SMB\\NativeState' => __DIR__ . '/..' . '/icewind/smb/src/NativeState.php',
'Icewind\\SMB\\NativeStream' => __DIR__ . '/..' . '/icewind/smb/src/NativeStream.php',
+ 'Icewind\\SMB\\NotifyHandler' => __DIR__ . '/..' . '/icewind/smb/src/NotifyHandler.php',
'Icewind\\SMB\\Parser' => __DIR__ . '/..' . '/icewind/smb/src/Parser.php',
'Icewind\\SMB\\RawConnection' => __DIR__ . '/..' . '/icewind/smb/src/RawConnection.php',
'Icewind\\SMB\\Server' => __DIR__ . '/..' . '/icewind/smb/src/Server.php',
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Change.php b/apps/files_external/3rdparty/icewind/smb/src/Change.php
new file mode 100644
index 00000000000..9dfd57b3973
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Change.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ *
+ */
+
+namespace Icewind\SMB;
+
+class Change {
+ private $code;
+
+ private $path;
+
+ /**
+ * Change constructor.
+ *
+ * @param $code
+ * @param $path
+ */
+ public function __construct($code, $path) {
+ $this->code = $code;
+ $this->path = $path;
+ }
+
+ /**
+ * @return integer
+ */
+ public function getCode() {
+ return $this->code;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPath() {
+ return $this->path;
+ }
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/Exception/DependencyException.php b/apps/files_external/3rdparty/icewind/smb/src/Exception/DependencyException.php
new file mode 100644
index 00000000000..39735578798
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/Exception/DependencyException.php
@@ -0,0 +1,11 @@
+<?php
+/**
+ * Copyright (c) 2016 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 DependencyException extends Exception {
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php
new file mode 100644
index 00000000000..1ee59b26ddd
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/INotifyHandler.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ *
+ */
+
+namespace Icewind\SMB;
+
+
+interface INotifyHandler {
+ // https://msdn.microsoft.com/en-us/library/dn392331.aspx
+ const NOTIFY_ADDED = 1;
+ const NOTIFY_REMOVED = 2;
+ const NOTIFY_MODIFIED = 3;
+ const NOTIFY_RENAMED_OLD = 4;
+ const NOTIFY_RENAMED_NEW = 5;
+ const NOTIFY_ADDED_STREAM = 6;
+ const NOTIFY_REMOVED_STREAM = 7;
+ const NOTIFY_MODIFIED_STREAM = 8;
+ const NOTIFY_REMOVED_BY_DELETE = 9;
+
+ /**
+ * Get all changes detected since the start of the notify process or the last call to getChanges
+ *
+ * @return Change[]
+ */
+ public function getChanges();
+
+ /**
+ * Listen actively to all incoming changes
+ *
+ * Note that this is a blocking process and will cause the process to block forever if not explicitly terminated
+ *
+ * @param callable $callback
+ */
+ public function listen($callback);
+
+ /**
+ * Stop listening for changes
+ *
+ * Note that any pending changes will be discarded
+ */
+ public function stop();
+}
diff --git a/apps/files_external/3rdparty/icewind/smb/src/NotifyHandler.php b/apps/files_external/3rdparty/icewind/smb/src/NotifyHandler.php
new file mode 100644
index 00000000000..194e848502b
--- /dev/null
+++ b/apps/files_external/3rdparty/icewind/smb/src/NotifyHandler.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Robin Appelman <robin@icewind.nl>
+ * This file is licensed under the Licensed under the MIT license:
+ * http://opensource.org/licenses/MIT
+ *
+ */
+
+namespace Icewind\SMB;
+
+
+class NotifyHandler implements INotifyHandler {
+ /**
+ * @var Connection
+ */
+ private $connection;
+
+ /**
+ * @var string
+ */
+ private $path;
+
+ private $listening = true;
+
+ /**
+ * @param Connection $connection
+ * @param string $path
+ */
+ public function __construct(Connection $connection, $path) {
+ $this->connection = $connection;
+ $this->path = $path;
+ }
+
+ /**
+ * Get all changes detected since the start of the notify process or the last call to getChanges
+ *
+ * @return Change[]
+ */
+ public function getChanges() {
+ if (!$this->listening) {
+ return [];
+ }
+ stream_set_blocking($this->connection->getOutputStream(), 0);
+ $lines = [];
+ while (($line = $this->connection->readLine())) {
+ $lines[] = $line;
+ }
+ stream_set_blocking($this->connection->getOutputStream(), 1);
+ return array_values(array_filter(array_map([$this, 'parseChangeLine'], $lines)));
+ }
+
+ /**
+ * Listen actively to all incoming changes
+ *
+ * Note that this is a blocking process and will cause the process to block forever if not explicitly terminated
+ *
+ * @param callable $callback
+ */
+ public function listen($callback) {
+ if ($this->listening) {
+ $this->connection->read(function ($line) use ($callback) {
+ return $callback($this->parseChangeLine($line));
+ });
+ }
+ }
+
+ private function parseChangeLine($line) {
+ $code = (int)substr($line, 0, 4);
+ if ($code === 0) {
+ return null;
+ }
+ $subPath = str_replace('\\', '/', substr($line, 5));
+ if ($this->path === '') {
+ return new Change($code, $subPath);
+ } else {
+ return new Change($code, $this->path . '/' . $subPath);
+ }
+ }
+
+ public function stop() {
+ $this->listening = false;
+ $this->connection->close();
+ }
+
+ public function __destruct() {
+ $this->stop();
+ }
+}
diff --git a/apps/files_external/l10n/zh_CN.js b/apps/files_external/l10n/zh_CN.js
index fcbee03772f..786d85e9099 100644
--- a/apps/files_external/l10n/zh_CN.js
+++ b/apps/files_external/l10n/zh_CN.js
@@ -1,32 +1,82 @@
OC.L10N.register(
"files_external",
{
- "Step 1 failed. Exception: %s" : "步骤 1 失败。异常:%s",
- "Step 2 failed. Exception: %s" : "步骤 2 失败。异常:%s",
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "获取 request token 失败. 请验证您的 appkey 和密钥是否正确.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "获取 access token 失败. 请验证您的 appkey 和密钥是否正确.",
+ "Please provide a valid app key and secret." : "请提供有效的 appkey 和密钥.",
+ "Step 1 failed. Exception: %s" : "步骤 1 失败. 异常: %s",
+ "Step 2 failed. Exception: %s" : "步骤 2 失败. 异常: %s",
"External storage" : "外部存储",
+ "Dropbox App Configuration" : "Dropbox 配置",
+ "Google Drive App Configuration" : "Google Drive 配置",
"Personal" : "个人",
"System" : "系统",
"Grant access" : "授权",
+ "Error configuring OAuth1" : "OAuth1 配置错误",
+ "Error configuring OAuth2" : "OAuth2 配置错误",
+ "Generate keys" : "生成密钥",
+ "Error generating key pair" : "生成密钥对错误",
+ "All users. Type to select user or group." : "全部用户. 点击选择用户或分组.",
+ "(group)" : "(分组)",
+ "Compatibility with Mac NFD encoding (slow)" : "兼用 Mac NFD 编码 (慢)",
+ "Admin defined" : "管理员定义",
"Saved" : "已保存",
+ "Saving..." : "正在保存...",
+ "Save" : "保存",
+ "Empty response from the server" : "服务器响应为空",
+ "Couldn't access. Please logout and login to activate this mount point" : "无法连接. 请注销并重新登录以激活挂载点.",
+ "Couldn't get the information from the remote server: {code} {type}" : "无法从远程服务器获取信息: {code} {type}",
+ "Couldn't get the list of external mount points: {type}" : "无法获取外部挂载点列表: {type}",
+ "There was an error with message: " : "错误信息: ",
"External mount error" : "外部挂载错误",
"external-storage" : "外部存储",
+ "Couldn't get the list of Windows network drive mount points: empty response from the server" : "无法获取 Windows 网络磁盘挂载点列表: 服务器响应为空",
+ "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "一些外部挂载点没有连接. 请检查标红的行以获取更多信息.",
+ "Please enter the credentials for the {mount} mount" : "请输入 {mount} 挂载点的凭据",
"Username" : "用户名",
"Password" : "密码",
- "Save" : "保存",
+ "Credentials saved" : "凭据已保存",
+ "Credentials saving failed" : "凭据保存失败",
+ "Credentials required" : "需要凭据",
+ "Storage with id \"%i\" not found" : "未找到 ID 为 \"%i\" 的存储",
+ "Invalid backend or authentication mechanism class" : "无效的后端或认证类型",
"Invalid mount point" : "无效的挂载点",
+ "Objectstore forbidden" : "对象存储禁止访问",
+ "Invalid storage backend \"%s\"" : "无效的存储后端 \"%s\"",
+ "Not permitted to use backend \"%s\"" : "不允许使用 \"%s\"",
+ "Not permitted to use authentication mechanism \"%s\"" : "不允许使用认证方式 \"%s\"",
+ "Unsatisfied backend parameters" : "无法满足后端条件",
+ "Unsatisfied authentication mechanism parameters" : "无法满足认证类型条件",
+ "Insufficient data: %s" : "数据不足: %s",
"%s" : "%s",
+ "Storage with id \"%i\" is not user editable" : "无法编辑 ID 为 \"%i\" 的存储",
"Access key" : "Access key",
"Secret key" : "Secret key",
"Builtin" : "内置",
"None" : "无",
+ "OAuth1" : "OAuth1",
+ "App key" : "App key",
+ "App secret" : "App 密钥",
+ "OAuth2" : "OAuth2",
+ "Client ID" : "Client ID",
+ "Client secret" : "客户端密钥",
+ "OpenStack" : "OpenStack",
+ "Tenant name" : "租户名称",
+ "Identity endpoint URL" : "身份识别 URL",
+ "Rackspace" : "Rackspace",
"API key" : "API密匙",
+ "Global credentials" : "全局凭据",
+ "Log-in credentials, save in database" : "登录凭据, 保存在数据库中",
"Username and password" : "用户名和密码",
+ "Log-in credentials, save in session" : "登录凭据, 存储在会话中",
+ "User entered, store in database" : "用户登录, 存储在数据库中",
"RSA public key" : "RSA 公钥",
"Public key" : "公钥",
"Amazon S3" : "Amazon S3",
+ "Bucket" : "Bucket",
"Hostname" : "主机名",
"Port" : "端口",
- "Region" : "地区",
+ "Region" : "区域",
"Enable SSL" : "启用 SSL",
"Enable Path Style" : "启用 Path Style",
"WebDAV" : "WebDAV",
@@ -40,20 +90,23 @@ OC.L10N.register(
"Google Drive" : "Google Drive",
"Local" : "本地",
"Location" : "地点",
- "ownCloud" : "ownCloud",
+ "Nextcloud" : "Nextcloud",
"SFTP" : "SFTP",
"Root" : "根路径",
- "SFTP with secret key login" : "包含secret key的SFTP",
+ "SFTP with secret key login" : "包含 secret key 的SFTP",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "共享",
"Domain" : "域名",
"SMB / CIFS using OC login" : "SMB / CIFS 使用 OC 登录信息",
+ "Username as share" : "以用户名作为共享名",
"OpenStack Object Storage" : "OpenStack 对象存储",
- "<b>Note:</b> " : "<b>注意:</b>",
- "<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 的挂载无法进行。请联系系统管理员进行安装。",
- "<b>Note:</b> The FTP 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 中的 FTP 支持未启用或未安装。对 %s 的挂载无法进行。请联系系统管理员进行安装。",
- "<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b>“%s”尚未安装。对 %s 的挂载无法进行。请联系系统管理员进行安装。",
- "No external storage configured" : "未配置外部存储",
+ "Service name" : "服务名称",
+ "Request timeout (seconds)" : "请求超时时间 (秒)",
+ "External storages" : "外部存储",
+ "The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "没有安装或启用 PHP 中的 cURL 支持. 无法挂载 %s. 请联系您的系统管理员安装.",
+ "The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "没有安装或启用 PHP 中的 FTP 支持. 无法挂载 %s. 请联系您的系统管理员安装.",
+ "\"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "没有安装 \"%s\". 无法挂载 %s. 请联系您的系统管理员安装.",
+ "No external storage configured" : "没有配置外部存储",
"You can add external storages in the personal settings" : "您可以在个人设置中添加外部存储",
"Name" : "名称",
"Storage type" : "存储类型",
@@ -61,8 +114,9 @@ OC.L10N.register(
"Enable encryption" : "启用加密",
"Enable previews" : "启用预览",
"Enable sharing" : "启用分享",
+ "Check for changes" : "检查修改",
"Never" : "从不",
- "External Storage" : "外部存储",
+ "Once every direct access" : "每次直接访问",
"Folder name" : "目录名称",
"Authentication" : "认证",
"Configuration" : "配置",
@@ -71,6 +125,7 @@ OC.L10N.register(
"Advanced settings" : "高级选项",
"Delete" : "删除",
"Allow users to mount external storage" : "允许用户挂载外部存储",
- "Allow users to mount the following external storage" : "允许用户挂载以下外部存储"
+ "Allow users to mount the following external storage" : "允许用户挂载以下外部存储",
+ "Couldn't get the information from the ownCloud server: {code} {type}" : "无法从 ownCloud 服务器获取信息: {code} {type}"
},
"nplurals=1; plural=0;");
diff --git a/apps/files_external/l10n/zh_CN.json b/apps/files_external/l10n/zh_CN.json
index 286156dac52..b6a656d6b4a 100644
--- a/apps/files_external/l10n/zh_CN.json
+++ b/apps/files_external/l10n/zh_CN.json
@@ -1,30 +1,80 @@
{ "translations": {
- "Step 1 failed. Exception: %s" : "步骤 1 失败。异常:%s",
- "Step 2 failed. Exception: %s" : "步骤 2 失败。异常:%s",
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "获取 request token 失败. 请验证您的 appkey 和密钥是否正确.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "获取 access token 失败. 请验证您的 appkey 和密钥是否正确.",
+ "Please provide a valid app key and secret." : "请提供有效的 appkey 和密钥.",
+ "Step 1 failed. Exception: %s" : "步骤 1 失败. 异常: %s",
+ "Step 2 failed. Exception: %s" : "步骤 2 失败. 异常: %s",
"External storage" : "外部存储",
+ "Dropbox App Configuration" : "Dropbox 配置",
+ "Google Drive App Configuration" : "Google Drive 配置",
"Personal" : "个人",
"System" : "系统",
"Grant access" : "授权",
+ "Error configuring OAuth1" : "OAuth1 配置错误",
+ "Error configuring OAuth2" : "OAuth2 配置错误",
+ "Generate keys" : "生成密钥",
+ "Error generating key pair" : "生成密钥对错误",
+ "All users. Type to select user or group." : "全部用户. 点击选择用户或分组.",
+ "(group)" : "(分组)",
+ "Compatibility with Mac NFD encoding (slow)" : "兼用 Mac NFD 编码 (慢)",
+ "Admin defined" : "管理员定义",
"Saved" : "已保存",
+ "Saving..." : "正在保存...",
+ "Save" : "保存",
+ "Empty response from the server" : "服务器响应为空",
+ "Couldn't access. Please logout and login to activate this mount point" : "无法连接. 请注销并重新登录以激活挂载点.",
+ "Couldn't get the information from the remote server: {code} {type}" : "无法从远程服务器获取信息: {code} {type}",
+ "Couldn't get the list of external mount points: {type}" : "无法获取外部挂载点列表: {type}",
+ "There was an error with message: " : "错误信息: ",
"External mount error" : "外部挂载错误",
"external-storage" : "外部存储",
+ "Couldn't get the list of Windows network drive mount points: empty response from the server" : "无法获取 Windows 网络磁盘挂载点列表: 服务器响应为空",
+ "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "一些外部挂载点没有连接. 请检查标红的行以获取更多信息.",
+ "Please enter the credentials for the {mount} mount" : "请输入 {mount} 挂载点的凭据",
"Username" : "用户名",
"Password" : "密码",
- "Save" : "保存",
+ "Credentials saved" : "凭据已保存",
+ "Credentials saving failed" : "凭据保存失败",
+ "Credentials required" : "需要凭据",
+ "Storage with id \"%i\" not found" : "未找到 ID 为 \"%i\" 的存储",
+ "Invalid backend or authentication mechanism class" : "无效的后端或认证类型",
"Invalid mount point" : "无效的挂载点",
+ "Objectstore forbidden" : "对象存储禁止访问",
+ "Invalid storage backend \"%s\"" : "无效的存储后端 \"%s\"",
+ "Not permitted to use backend \"%s\"" : "不允许使用 \"%s\"",
+ "Not permitted to use authentication mechanism \"%s\"" : "不允许使用认证方式 \"%s\"",
+ "Unsatisfied backend parameters" : "无法满足后端条件",
+ "Unsatisfied authentication mechanism parameters" : "无法满足认证类型条件",
+ "Insufficient data: %s" : "数据不足: %s",
"%s" : "%s",
+ "Storage with id \"%i\" is not user editable" : "无法编辑 ID 为 \"%i\" 的存储",
"Access key" : "Access key",
"Secret key" : "Secret key",
"Builtin" : "内置",
"None" : "无",
+ "OAuth1" : "OAuth1",
+ "App key" : "App key",
+ "App secret" : "App 密钥",
+ "OAuth2" : "OAuth2",
+ "Client ID" : "Client ID",
+ "Client secret" : "客户端密钥",
+ "OpenStack" : "OpenStack",
+ "Tenant name" : "租户名称",
+ "Identity endpoint URL" : "身份识别 URL",
+ "Rackspace" : "Rackspace",
"API key" : "API密匙",
+ "Global credentials" : "全局凭据",
+ "Log-in credentials, save in database" : "登录凭据, 保存在数据库中",
"Username and password" : "用户名和密码",
+ "Log-in credentials, save in session" : "登录凭据, 存储在会话中",
+ "User entered, store in database" : "用户登录, 存储在数据库中",
"RSA public key" : "RSA 公钥",
"Public key" : "公钥",
"Amazon S3" : "Amazon S3",
+ "Bucket" : "Bucket",
"Hostname" : "主机名",
"Port" : "端口",
- "Region" : "地区",
+ "Region" : "区域",
"Enable SSL" : "启用 SSL",
"Enable Path Style" : "启用 Path Style",
"WebDAV" : "WebDAV",
@@ -38,20 +88,23 @@
"Google Drive" : "Google Drive",
"Local" : "本地",
"Location" : "地点",
- "ownCloud" : "ownCloud",
+ "Nextcloud" : "Nextcloud",
"SFTP" : "SFTP",
"Root" : "根路径",
- "SFTP with secret key login" : "包含secret key的SFTP",
+ "SFTP with secret key login" : "包含 secret key 的SFTP",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "共享",
"Domain" : "域名",
"SMB / CIFS using OC login" : "SMB / CIFS 使用 OC 登录信息",
+ "Username as share" : "以用户名作为共享名",
"OpenStack Object Storage" : "OpenStack 对象存储",
- "<b>Note:</b> " : "<b>注意:</b>",
- "<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 的挂载无法进行。请联系系统管理员进行安装。",
- "<b>Note:</b> The FTP 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 中的 FTP 支持未启用或未安装。对 %s 的挂载无法进行。请联系系统管理员进行安装。",
- "<b>Note:</b> \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "<b>注意:</b>“%s”尚未安装。对 %s 的挂载无法进行。请联系系统管理员进行安装。",
- "No external storage configured" : "未配置外部存储",
+ "Service name" : "服务名称",
+ "Request timeout (seconds)" : "请求超时时间 (秒)",
+ "External storages" : "外部存储",
+ "The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "没有安装或启用 PHP 中的 cURL 支持. 无法挂载 %s. 请联系您的系统管理员安装.",
+ "The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "没有安装或启用 PHP 中的 FTP 支持. 无法挂载 %s. 请联系您的系统管理员安装.",
+ "\"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "没有安装 \"%s\". 无法挂载 %s. 请联系您的系统管理员安装.",
+ "No external storage configured" : "没有配置外部存储",
"You can add external storages in the personal settings" : "您可以在个人设置中添加外部存储",
"Name" : "名称",
"Storage type" : "存储类型",
@@ -59,8 +112,9 @@
"Enable encryption" : "启用加密",
"Enable previews" : "启用预览",
"Enable sharing" : "启用分享",
+ "Check for changes" : "检查修改",
"Never" : "从不",
- "External Storage" : "外部存储",
+ "Once every direct access" : "每次直接访问",
"Folder name" : "目录名称",
"Authentication" : "认证",
"Configuration" : "配置",
@@ -69,6 +123,7 @@
"Advanced settings" : "高级选项",
"Delete" : "删除",
"Allow users to mount external storage" : "允许用户挂载外部存储",
- "Allow users to mount the following external storage" : "允许用户挂载以下外部存储"
+ "Allow users to mount the following external storage" : "允许用户挂载以下外部存储",
+ "Couldn't get the information from the ownCloud server: {code} {type}" : "无法从 ownCloud 服务器获取信息: {code} {type}"
},"pluralForm" :"nplurals=1; plural=0;"
} \ No newline at end of file
diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php
index 913299b59b4..a55b16a45c4 100644
--- a/apps/files_external/lib/Command/Notify.php
+++ b/apps/files_external/lib/Command/Notify.php
@@ -27,7 +27,11 @@ use OC\Core\Command\Base;
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
use OCA\Files_External\Lib\StorageConfig;
use OCA\Files_External\Service\GlobalStoragesService;
+use OCP\Files\Notify\IChange;
+use OCP\Files\Notify\INotifyHandler;
+use OCP\Files\Notify\IRenameChange;
use OCP\Files\Storage\INotifyStorage;
+use OCP\Files\Storage\IStorage;
use OCP\Files\StorageNotAvailableException;
use OCP\IDBConnection;
use Symfony\Component\Console\Input\InputArgument;
@@ -123,14 +127,16 @@ class Notify extends Base {
$verbose = $input->getOption('verbose');
$path = trim($input->getOption('path'), '/');
- $storage->listen($path, function ($type, $path, $renameTarget) use ($mount, $verbose, $output) {
+ $notifyHandler = $storage->notify($path);
+ $this->selfTest($storage, $notifyHandler, $verbose, $output);
+ $notifyHandler->listen(function (IChange $change) use ($mount, $verbose, $output) {
if ($verbose) {
- $this->logUpdate($type, $path, $renameTarget, $output);
+ $this->logUpdate($change, $output);
}
- if ($type == INotifyStorage::NOTIFY_RENAMED) {
- $this->markParentAsOutdated($mount->getId(), $renameTarget);
+ if ($change instanceof IRenameChange) {
+ $this->markParentAsOutdated($mount->getId(), $change->getTargetPath());
}
- $this->markParentAsOutdated($mount->getId(), $path);
+ $this->markParentAsOutdated($mount->getId(), $change->getPath());
});
}
@@ -147,8 +153,8 @@ class Notify extends Base {
$this->updateQuery->execute([$parent, $mountId]);
}
- private function logUpdate($type, $path, $renameTarget, OutputInterface $output) {
- switch ($type) {
+ private function logUpdate(IChange $change, OutputInterface $output) {
+ switch ($change->getType()) {
case INotifyStorage::NOTIFY_ADDED:
$text = 'added';
break;
@@ -165,11 +171,42 @@ class Notify extends Base {
return;
}
- $text .= ' ' . $path;
- if ($type === INotifyStorage::NOTIFY_RENAMED) {
- $text .= ' to ' . $renameTarget;
+ $text .= ' ' . $change->getPath();
+ if ($change instanceof IRenameChange) {
+ $text .= ' to ' . $change->getTargetPath();
}
$output->writeln($text);
}
+
+ private function selfTest(IStorage $storage, INotifyHandler $notifyHandler, $verbose, OutputInterface $output) {
+ usleep(100 * 1000); //give time for the notify to start
+ $storage->file_put_contents('/.nc_test_file.txt', 'test content');
+ $storage->mkdir('/.nc_test_folder');
+ $storage->file_put_contents('/.nc_test_folder/subfile.txt', 'test content');
+ $storage->unlink('/.nc_test_file.txt');
+ $storage->unlink('/.nc_test_folder/subfile.txt');
+ $storage->rmdir('/.nc_test_folder');
+ usleep(100 * 1000); //time for all changes to be processed
+
+ $foundRootChange = false;
+ $foundSubfolderChange = false;
+
+ $changes = $notifyHandler->getChanges();
+ foreach ($changes as $change) {
+ if ($change->getPath() === '/.nc_test_file.txt') {
+ $foundRootChange = true;
+ } else if ($change->getPath() === '/.nc_test_folder/subfile.txt') {
+ $foundSubfolderChange = true;
+ }
+ }
+
+ if ($foundRootChange && $foundSubfolderChange && $verbose) {
+ $output->writeln('<info>Self-test successful</info>');
+ } else if ($foundRootChange && !$foundSubfolderChange) {
+ $output->writeln('<error>Error while running self-test, change is subfolder not detected</error>');
+ } else if (!$foundRootChange) {
+ $output->writeln('<error>Error while running self-test, no changes detected</error>');
+ }
+ }
}
diff --git a/apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php b/apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php
new file mode 100644
index 00000000000..9ac74b32ad8
--- /dev/null
+++ b/apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php
@@ -0,0 +1,150 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Files_External\Lib\Notify;
+
+use OC\Files\Notify\Change;
+use OC\Files\Notify\RenameChange;
+use OCP\Files\Notify\IChange;
+use OCP\Files\Notify\INotifyHandler;
+
+class SMBNotifyHandler implements INotifyHandler {
+ /**
+ * @var \Icewind\SMB\INotifyHandler
+ */
+ private $shareNotifyHandler;
+
+ /**
+ * @var string
+ */
+ private $root;
+
+ private $oldRenamePath = null;
+
+ /**
+ * SMBNotifyHandler constructor.
+ *
+ * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler
+ * @param string $root
+ */
+ public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) {
+ $this->shareNotifyHandler = $shareNotifyHandler;
+ $this->root = $root;
+ }
+
+ private function relativePath($fullPath) {
+ if ($fullPath === $this->root) {
+ return '';
+ } else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
+ return substr($fullPath, strlen($this->root));
+ } else {
+ return null;
+ }
+ }
+
+ public function listen(callable $callback) {
+ $oldRenamePath = null;
+ $this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
+ $change = $this->mapChange($shareChange);
+ if (!is_null($change)) {
+ return $callback($change);
+ } else {
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Get all changes detected since the start of the notify process or the last call to getChanges
+ *
+ * @return IChange[]
+ */
+ public function getChanges() {
+ $shareChanges = $this->shareNotifyHandler->getChanges();
+ $changes = [];
+ foreach ($shareChanges as $shareChange) {
+ $change = $this->mapChange($shareChange);
+ if ($change) {
+ $changes[] = $change;
+ }
+ }
+ return $changes;
+ }
+
+ /**
+ * Stop listening for changes
+ *
+ * Note that any pending changes will be discarded
+ */
+ public function stop() {
+ $this->shareNotifyHandler->stop();
+ }
+
+ /**
+ * @param \Icewind\SMB\Change $change
+ * @return IChange|null
+ */
+ private function mapChange(\Icewind\SMB\Change $change) {
+ $path = $this->relativePath($change->getPath());
+ if (is_null($path)) {
+ return null;
+ }
+ if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) {
+ $this->oldRenamePath = $path;
+ return null;
+ }
+ $type = $this->mapNotifyType($change->getCode());
+ if (is_null($type)) {
+ return null;
+ }
+ if ($type === IChange::RENAMED) {
+ if (!is_null($this->oldRenamePath)) {
+ $result = new RenameChange($type, $this->oldRenamePath, $path);
+ $this->oldRenamePath = null;
+ } else {
+ $result = null;
+ }
+ } else {
+ $result = new Change($type, $path);
+ }
+ return $result;
+ }
+
+ private function mapNotifyType($smbType) {
+ switch ($smbType) {
+ case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED:
+ return IChange::ADDED;
+ case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED:
+ return IChange::REMOVED;
+ case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED:
+ case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM:
+ case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM:
+ case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM:
+ return IChange::MODIFIED;
+ case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW:
+ return IChange::RENAMED;
+ default:
+ return null;
+ }
+ }
+}
diff --git a/apps/files_external/lib/Lib/Storage/SFTP.php b/apps/files_external/lib/Lib/Storage/SFTP.php
index 9d20742fcb0..1d9affa8d68 100644
--- a/apps/files_external/lib/Lib/Storage/SFTP.php
+++ b/apps/files_external/lib/Lib/Storage/SFTP.php
@@ -207,7 +207,7 @@ class SFTP extends \OC\Files\Storage\Common {
try {
$storage_view = \OCP\Files::getStorage('files_external');
if ($storage_view) {
- return \OC::$server->getConfig()->getSystemValue('datadirectory') .
+ return \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') .
$storage_view->getAbsolutePath('') .
'ssh_hostKeys';
}
diff --git a/apps/files_external/lib/Lib/Storage/SMB.php b/apps/files_external/lib/Lib/Storage/SMB.php
index 7ffc078df6f..690f8e2a334 100644
--- a/apps/files_external/lib/Lib/Storage/SMB.php
+++ b/apps/files_external/lib/Lib/Storage/SMB.php
@@ -46,6 +46,9 @@ use Icewind\Streams\IteratorDirectory;
use OC\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
use OC\Files\Storage\Common;
+use OCA\Files_External\Lib\Notify\SMBNotifyHandler;
+use OCP\Files\Notify\IChange;
+use OCP\Files\Notify\IRenameChange;
use OCP\Files\Storage\INotifyStorage;
use OCP\Files\StorageNotAvailableException;
@@ -149,7 +152,7 @@ class SMB extends Common implements INotifyStorage {
foreach ($files as $file) {
$this->statCache[$path . '/' . $file->getName()] = $file;
}
- return array_filter($files, function(IFileInfo $file) {
+ return array_filter($files, function (IFileInfo $file) {
return !$file->isHidden();
});
} catch (ConnectException $e) {
@@ -486,48 +489,18 @@ class SMB extends Common implements INotifyStorage {
}
public function listen($path, callable $callback) {
- $fullPath = $this->buildPath($path);
- $oldRenamePath = null;
- $this->share->notify($fullPath)->listen(function (Change $change) use (&$oldRenamePath, $callback) {
- $path = $this->relativePath($change->getPath());
- if (is_null($path)) {
- return true;
- }
- if ($change->getCode() === INotifyHandler::NOTIFY_RENAMED_OLD) {
- $oldRenamePath = $path;
- return true;
- }
- $type = $this->mapNotifyType($change->getCode());
- if (is_null($type)) {
- return true;
- }
- if ($type === INotifyStorage::NOTIFY_RENAMED) {
- if (!is_null($oldRenamePath)) {
- $result = $callback($type, $oldRenamePath, $path);
- $oldRenamePath = null;
- }
+ $this->notify($path)->listen(function (IChange $change) use ($callback) {
+ if ($change instanceof IRenameChange) {
+ return $callback($change->getType(), $change->getPath(), $change->getTargetPath());
} else {
- $result = $callback($type, $path);
+ return $callback($change->getType(), $change->getPath());
}
- return $result;
});
}
- private function mapNotifyType($smbType) {
- switch ($smbType) {
- case INotifyHandler::NOTIFY_ADDED:
- return INotifyStorage::NOTIFY_ADDED;
- case INotifyHandler::NOTIFY_REMOVED:
- return INotifyStorage::NOTIFY_REMOVED;
- case INotifyHandler::NOTIFY_MODIFIED:
- case INotifyHandler::NOTIFY_ADDED_STREAM:
- case INotifyHandler::NOTIFY_MODIFIED_STREAM:
- case INotifyHandler::NOTIFY_REMOVED_STREAM:
- return INotifyStorage::NOTIFY_MODIFIED;
- case INotifyHandler::NOTIFY_RENAMED_NEW:
- return INotifyStorage::NOTIFY_RENAMED;
- default:
- return null;
- }
+ public function notify($path) {
+ $path = '/' . ltrim($path, '/');
+ $shareNotifyHandler = $this->share->notify($this->buildPath($path));
+ return new SMBNotifyHandler($shareNotifyHandler, $this->root);
}
}
diff --git a/apps/files_external/tests/Storage/SmbTest.php b/apps/files_external/tests/Storage/SmbTest.php
index 150d4d3a035..45c01a0c59e 100644
--- a/apps/files_external/tests/Storage/SmbTest.php
+++ b/apps/files_external/tests/Storage/SmbTest.php
@@ -27,7 +27,10 @@
namespace OCA\Files_External\Tests\Storage;
+use OC\Files\Notify\Change;
+use OC\Files\Notify\RenameChange;
use \OCA\Files_External\Lib\Storage\SMB;
+use OCP\Files\Notify\IChange;
/**
* Class SmbTest
@@ -37,6 +40,10 @@ use \OCA\Files_External\Lib\Storage\SMB;
* @package OCA\Files_External\Tests\Storage
*/
class SmbTest extends \Test\Files\Storage\Storage {
+ /**
+ * @var SMB instance
+ */
+ protected $instance;
protected function setUp() {
parent::setUp();
@@ -85,4 +92,44 @@ class SmbTest extends \Test\Files\Storage\Storage {
$this->assertEquals('smb::testuser@testhost//someshare//someroot/', $this->instance->getId());
$this->instance = null;
}
+
+ public function testNotifyGetChanges() {
+ $notifyHandler = $this->instance->notify('');
+ usleep(100 * 1000); //give time for the notify to start
+ $this->instance->file_put_contents('/newfile.txt', 'test content');
+ $this->instance->rename('/newfile.txt', 'renamed.txt');
+ $this->instance->unlink('/renamed.txt');
+ usleep(100 * 1000); //time for all changes to be processed
+
+ $changes = $notifyHandler->getChanges();
+ $notifyHandler->stop();
+
+ $expected = [
+ new Change(IChange::ADDED, 'newfile.txt'),
+ new RenameChange(IChange::RENAMED, 'newfile.txt', 'renamed.txt'),
+ new Change(IChange::REMOVED, 'renamed.txt')
+ ];
+
+ foreach ($expected as $expectedChange) {
+ $this->assertContains($expectedChange, $changes, '', false, false); // dont check object identity
+ }
+ }
+
+ public function testNotifyListen() {
+ $notifyHandler = $this->instance->notify('');
+ usleep(100 * 1000); //give time for the notify to start
+ $this->instance->file_put_contents('/newfile.txt', 'test content');
+ $this->instance->unlink('/newfile.txt');
+ usleep(100 * 1000); //time for all changes to be processed
+
+ $result = null;
+
+ // since the notify handler buffers untill we start listening we will get the above changes
+ $notifyHandler->listen(function (IChange $change) use (&$result) {
+ $result = $change;
+ return false;//stop listening
+ });
+
+ $this->assertEquals(new Change(IChange::ADDED, 'newfile.txt'), $result);
+ }
}
diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php
index e73d6b0ac69..2e66a6b96e1 100644
--- a/apps/files_trashbin/lib/Trashbin.php
+++ b/apps/files_trashbin/lib/Trashbin.php
@@ -902,7 +902,7 @@ class Trashbin {
* @return integer size of the folder
*/
private static function calculateSize($view) {
- $root = \OC::$server->getConfig()->getSystemValue('datadirectory') . $view->getAbsolutePath('');
+ $root = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath('');
if (!file_exists($root)) {
return 0;
}
diff --git a/apps/theming/lib/Util.php b/apps/theming/lib/Util.php
index 9fea56838ad..5c9ccb3baa6 100644
--- a/apps/theming/lib/Util.php
+++ b/apps/theming/lib/Util.php
@@ -128,7 +128,7 @@ class Util {
} catch (AppPathNotFoundException $e) {}
if($this->config->getAppValue('theming', 'logoMime', '') !== '' && $this->rootFolder->nodeExists('/themedinstancelogo')) {
- return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/') . '/themedinstancelogo';
+ return $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/themedinstancelogo';
}
return \OC::$SERVERROOT . '/core/img/logo.svg';
}
diff --git a/apps/twofactor_backupcodes/l10n/lv.js b/apps/twofactor_backupcodes/l10n/lv.js
index 8d0aba6bab3..80d28c47db7 100644
--- a/apps/twofactor_backupcodes/l10n/lv.js
+++ b/apps/twofactor_backupcodes/l10n/lv.js
@@ -11,6 +11,8 @@ OC.L10N.register(
"An error occurred while generating your backup codes" : "Radās kļūda, ģenerējot jūsu dublējuma kodus",
"Nextcloud backup codes" : "Nextcloud dublēšanas kodi",
"Two-factor authentication" : "Divpakāpju autentifikācija",
+ "You successfully logged in using two-factor authentication (%1$s)" : "Esat veiksmīgi pieteicies, izmantojot divpakāpju autentifikācija (%1$s)",
+ "You created two-factor backup codes for your account" : "Jūs izveidojāt divpakāpju dublējumu kodus savam kontam",
"Backup code" : "Dublēšanas kods",
"Use backup code" : "Izmantojiet dublēšanas kodu"
},
diff --git a/apps/twofactor_backupcodes/l10n/lv.json b/apps/twofactor_backupcodes/l10n/lv.json
index 35cd09352c2..6a65642a248 100644
--- a/apps/twofactor_backupcodes/l10n/lv.json
+++ b/apps/twofactor_backupcodes/l10n/lv.json
@@ -9,6 +9,8 @@
"An error occurred while generating your backup codes" : "Radās kļūda, ģenerējot jūsu dublējuma kodus",
"Nextcloud backup codes" : "Nextcloud dublēšanas kodi",
"Two-factor authentication" : "Divpakāpju autentifikācija",
+ "You successfully logged in using two-factor authentication (%1$s)" : "Esat veiksmīgi pieteicies, izmantojot divpakāpju autentifikācija (%1$s)",
+ "You created two-factor backup codes for your account" : "Jūs izveidojāt divpakāpju dublējumu kodus savam kontam",
"Backup code" : "Dublēšanas kods",
"Use backup code" : "Izmantojiet dublēšanas kodu"
},"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"
diff --git a/core/css/apps.scss b/core/css/apps.scss
index bb9326fd22d..f1ddc95e092 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -62,12 +62,26 @@ em {
-ms-user-select: none;
user-select: none;
border-right: 1px solid #eee;
+ display: flex;
+ flex-direction: column;
> ul {
position: relative;
height: 100%;
width: inherit;
overflow: auto;
box-sizing: border-box;
+ > li {
+ &:focus,
+ &:hover,
+ &.active,
+ a.selected {
+ &,
+ > a {
+ opacity: 1;
+ box-shadow: inset 2px 0 #0082c9;
+ }
+ }
+ }
}
li {
position: relative;
@@ -104,16 +118,6 @@ em {
color: #000;
opacity: .57;
}
- li:hover > a,
- li:focus > a,
- a:focus,
- .selected,
- .selected a,
- .active,
- .active a {
- opacity: 1;
- box-shadow: inset 2px 0 #0082c9;
- }
li > a:first-child img {
margin-bottom: -3px;
margin-right: 11px;
@@ -559,7 +563,6 @@ em {
background-color: #fff;
color: #333;
border-radius: 3px;
- border-top-right-radius: 0;
z-index: 110;
margin: 5px;
margin-top: -5px;
@@ -592,7 +595,6 @@ em {
transform: translateX(50%);
right: 50%;
margin-right: 0;
- border-top-right-radius: 3px;
&:after {
right: 50%;
transform: translateX(50%);
@@ -603,8 +605,6 @@ em {
right: auto;
left: 0;
margin-right: 0;
- border-top-left-radius: 0;
- border-top-right-radius: 3px;
&:after {
left: 6px;
right: auto;
@@ -639,6 +639,7 @@ em {
margin: 0;
font-weight: inherit;
box-shadow: none;
+ color: #333 !important; /* Overwrite app-navigation li */
/* prevent .action class to break the design */
&.action {
padding: inherit !important;
@@ -653,15 +654,15 @@ em {
cursor: pointer;
white-space: nowrap;
}
+ span {
+ -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=70)' !important;
+ filter: alpha(opacity = 70) !important;
+ opacity: .7 !important;
+ }
> p {
width: 150px;
line-height: 1.6em;
padding: 8px 0;
- > span {
- -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=70)' !important;
- filter: alpha(opacity = 70) !important;
- opacity: .7 !important;
- }
}
/* Add padding if contains icon+text */
&:not(:empty) {
@@ -680,7 +681,8 @@ em {
padding: 18px 0 18px 36px;
min-width: 0; /* Overwrite icons*/
min-height: 0;
- background-position: 10px center
+ background-position: 10px center;
+ opacity: 0.7; /* Default button icon override */
}
}
}
diff --git a/core/css/header.scss b/core/css/header.scss
index 21b8cff4d28..2b73937a3c4 100644
--- a/core/css/header.scss
+++ b/core/css/header.scss
@@ -20,6 +20,21 @@
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
+
+ /* Dropdown menu arrow */
+ &.menu:after,
+ .menu:after {
+ border: 10px solid transparent;
+ border-color: transparent;
+ border-bottom-color: #fff;
+ bottom: 100%;
+ content: ' ';
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+ margin-left: -10px;
+ }
}
/* removed until content-focusing issue is fixed */
@@ -194,21 +209,8 @@
border-top-right-radius: 0;
display: none;
box-sizing: border-box;
- /*overflow-y: auto;
- overflow-x: hidden;*/
z-index: 2000;
&:after {
- bottom: 100%;
- border: solid transparent;
- content: ' ';
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
- border-color: rgba(0, 0, 0, 0);
- border-bottom-color: rgba(255, 255, 255, 0.97);
- border-width: 10px;
- margin-left: -10px;
left: 47%;
}
* {
@@ -381,16 +383,6 @@
&:after {
/* position of dropdown arrow */
right: 15px;
- border: 10px solid transparent;
- border-color: transparent;
- border-bottom-color: #fff;
- bottom: 100%;
- content: ' ';
- height: 0;
- width: 0;
- position: absolute;
- pointer-events: none;
- margin-left: -10px;
}
a {
display: block;
diff --git a/core/l10n/zh_CN.js b/core/l10n/zh_CN.js
index 47101cfe384..1ce7f1c45f3 100644
--- a/core/l10n/zh_CN.js
+++ b/core/l10n/zh_CN.js
@@ -146,7 +146,7 @@ OC.L10N.register(
"An error occurred. Please try again" : "发生错误. 请重试.",
"{sharee} (group)" : "{sharee} (分组)",
"{sharee} (remote)" : "{sharee} (外部)",
- "{sharee} (email)" : "{sharee} (邮件)",
+ "{sharee} (email)" : "{sharee} (邮件)",
"Share" : "分享",
"Share with people on other servers using their Federated Cloud ID username@example.com/nextcloud" : "使用联合云ID与其他服务器的用户分享, 如 用户名@example.com/nextcloud",
"Share with users or by mail..." : "通过邮件分享...",
@@ -309,13 +309,13 @@ OC.L10N.register(
"Thu." : "周四",
"Fri." : "周五",
"Sat." : "周六",
- "Su" : "日",
- "Mo" : "一",
+ "Su" : "日",
+ "Mo" : "一",
"Tu" : "二",
- "We" : "三",
+ "We" : "三",
"Th" : "四",
"Fr" : "五",
- "Sa" : "六",
+ "Sa" : "六",
"January" : "一月",
"February" : "二月",
"March" : "三月",
diff --git a/core/l10n/zh_CN.json b/core/l10n/zh_CN.json
index 23134b325d7..bac9b3468a1 100644
--- a/core/l10n/zh_CN.json
+++ b/core/l10n/zh_CN.json
@@ -144,7 +144,7 @@
"An error occurred. Please try again" : "发生错误. 请重试.",
"{sharee} (group)" : "{sharee} (分组)",
"{sharee} (remote)" : "{sharee} (外部)",
- "{sharee} (email)" : "{sharee} (邮件)",
+ "{sharee} (email)" : "{sharee} (邮件)",
"Share" : "分享",
"Share with people on other servers using their Federated Cloud ID username@example.com/nextcloud" : "使用联合云ID与其他服务器的用户分享, 如 用户名@example.com/nextcloud",
"Share with users or by mail..." : "通过邮件分享...",
@@ -307,13 +307,13 @@
"Thu." : "周四",
"Fri." : "周五",
"Sat." : "周六",
- "Su" : "日",
- "Mo" : "一",
+ "Su" : "日",
+ "Mo" : "一",
"Tu" : "二",
- "We" : "三",
+ "We" : "三",
"Th" : "四",
"Fr" : "五",
- "Sa" : "六",
+ "Sa" : "六",
"January" : "一月",
"February" : "二月",
"March" : "三月",
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 5e00b31ae41..9c4a2f2728b 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -131,6 +131,9 @@ return array(
'OCP\\Files\\NotEnoughSpaceException' => $baseDir . '/lib/public/Files/NotEnoughSpaceException.php',
'OCP\\Files\\NotFoundException' => $baseDir . '/lib/public/Files/NotFoundException.php',
'OCP\\Files\\NotPermittedException' => $baseDir . '/lib/public/Files/NotPermittedException.php',
+ 'OCP\\Files\\Notify\\IChange' => $baseDir . '/lib/public/Files/Notify/IChange.php',
+ 'OCP\\Files\\Notify\\INotifyHandler' => $baseDir . '/lib/public/Files/Notify/INotifyHandler.php',
+ 'OCP\\Files\\Notify\\IRenameChange' => $baseDir . '/lib/public/Files/Notify/IRenameChange.php',
'OCP\\Files\\ObjectStore\\IObjectStore' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStore.php',
'OCP\\Files\\ReservedWordException' => $baseDir . '/lib/public/Files/ReservedWordException.php',
'OCP\\Files\\SimpleFS\\ISimpleFile' => $baseDir . '/lib/public/Files/SimpleFS/ISimpleFile.php',
@@ -527,6 +530,8 @@ return array(
'OC\\Files\\Node\\NonExistingFile' => $baseDir . '/lib/private/Files/Node/NonExistingFile.php',
'OC\\Files\\Node\\NonExistingFolder' => $baseDir . '/lib/private/Files/Node/NonExistingFolder.php',
'OC\\Files\\Node\\Root' => $baseDir . '/lib/private/Files/Node/Root.php',
+ 'OC\\Files\\Notify\\Change' => $baseDir . '/lib/private/Files/Notify/Change.php',
+ 'OC\\Files\\Notify\\RenameChange' => $baseDir . '/lib/private/Files/Notify/RenameChange.php',
'OC\\Files\\ObjectStore\\HomeObjectStoreStorage' => $baseDir . '/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php',
'OC\\Files\\ObjectStore\\Mapper' => $baseDir . '/lib/private/Files/ObjectStore/Mapper.php',
'OC\\Files\\ObjectStore\\NoopScanner' => $baseDir . '/lib/private/Files/ObjectStore/NoopScanner.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 040a1e0d2d3..de1047e9729 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -161,6 +161,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Files\\NotEnoughSpaceException' => __DIR__ . '/../../..' . '/lib/public/Files/NotEnoughSpaceException.php',
'OCP\\Files\\NotFoundException' => __DIR__ . '/../../..' . '/lib/public/Files/NotFoundException.php',
'OCP\\Files\\NotPermittedException' => __DIR__ . '/../../..' . '/lib/public/Files/NotPermittedException.php',
+ 'OCP\\Files\\Notify\\IChange' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/IChange.php',
+ 'OCP\\Files\\Notify\\INotifyHandler' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/INotifyHandler.php',
+ 'OCP\\Files\\Notify\\IRenameChange' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/IRenameChange.php',
'OCP\\Files\\ObjectStore\\IObjectStore' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStore.php',
'OCP\\Files\\ReservedWordException' => __DIR__ . '/../../..' . '/lib/public/Files/ReservedWordException.php',
'OCP\\Files\\SimpleFS\\ISimpleFile' => __DIR__ . '/../../..' . '/lib/public/Files/SimpleFS/ISimpleFile.php',
@@ -557,6 +560,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Files\\Node\\NonExistingFile' => __DIR__ . '/../../..' . '/lib/private/Files/Node/NonExistingFile.php',
'OC\\Files\\Node\\NonExistingFolder' => __DIR__ . '/../../..' . '/lib/private/Files/Node/NonExistingFolder.php',
'OC\\Files\\Node\\Root' => __DIR__ . '/../../..' . '/lib/private/Files/Node/Root.php',
+ 'OC\\Files\\Notify\\Change' => __DIR__ . '/../../..' . '/lib/private/Files/Notify/Change.php',
+ 'OC\\Files\\Notify\\RenameChange' => __DIR__ . '/../../..' . '/lib/private/Files/Notify/RenameChange.php',
'OC\\Files\\ObjectStore\\HomeObjectStoreStorage' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/HomeObjectStoreStorage.php',
'OC\\Files\\ObjectStore\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Mapper.php',
'OC\\Files\\ObjectStore\\NoopScanner' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/NoopScanner.php',
diff --git a/lib/l10n/zh_CN.js b/lib/l10n/zh_CN.js
index 05aa8cab94e..e2c683b68bb 100644
--- a/lib/l10n/zh_CN.js
+++ b/lib/l10n/zh_CN.js
@@ -2,19 +2,24 @@ OC.L10N.register(
"lib",
{
"Cannot write into \"config\" directory!" : "无法写入 \"config\" 目录!",
- "This can usually be fixed by giving the webserver write access to the config directory" : "对 Web 服务器设置 config 目录的写权限可以修复这个问题.",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "您可以设置 Web 服务器对 config 目录的写权限修复这个问题",
"See %s" : "查看 %s",
- "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "对 Web 服务器%s设置 config 目录%s的写权限可以修复这个问题.",
+ "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "您可以由 %s 设置 Web 服务器对 config 目录 %s 的写权限修复这个问题",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "应用 %$1s 的文件替换不正确. 请确认版本与当前服务器兼容.",
"Sample configuration detected" : "示例配置检测",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "您似乎直接把 config.php 的样例文件直接复制使用. 这可能会破坏您的安装. 在对 config.php 进行修改之前请先阅读相关文档.",
"%1$s and %2$s" : "%1$s 和 %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s 和 %3$s",
"%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s 和 %4$s",
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s 和 %5$s",
"PHP %s or higher is required." : "要求 PHP 版本 %s 或者更高。",
"PHP with a version lower than %s is required." : "需要版本低于 %s 的PHP.",
+ "%sbit or higher PHP required." : "需要 %s 或更高版本的 PHP",
"Following databases are supported: %s" : "支持以下数据库: %s",
"The command line tool %s could not be found" : "命令行工具 %s 未找到",
"The library %s is not available." : "库文件 %s 不可用",
+ "Library %s with a version higher than %s is required - available version %s." : "%s 需要 %s 或更高的版本 - 可用版本 %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "%s 需要 %s 或更低的版本 - 可用版本 %s.",
"Following platforms are supported: %s" : "支持以下平台:%s",
"Server version %s or higher is required." : "需要服务器版本 %s 或更高版本。",
"Server version %s or lower is required." : "需要服务器版本 %s 或更低版本。",
@@ -31,6 +36,7 @@ OC.L10N.register(
"_%n hour ago_::_%n hours ago_" : ["%n 小时前"],
"_%n minute ago_::_%n minutes ago_" : ["%n 分钟前"],
"seconds ago" : "秒前",
+ "Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID 为 %s 的模块不存在. 请在应用设置中启用或联系您的管理员.",
"File name is a reserved word" : "文件名包含敏感字符",
"File name contains at least one invalid character" : "文件名中存在至少一个非法字符",
"File name is too long" : "文件名过长",
@@ -64,27 +70,37 @@ OC.L10N.register(
"Invalid Federated Cloud ID" : "无效的联合云ID",
"%s shared »%s« with you" : "%s 向您分享了 »%s«",
"%s via %s" : "%s 通过 %s",
- "Sharing %s failed, because the file does not exist" : "共享 %s 失败,因为文件不存在。",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "分享 %s 失败, 因为后端不允许分享 %i 类型",
+ "Sharing %s failed, because the file does not exist" : "分享 %s 失败, 因为文件不存在.",
"You are not allowed to share %s" : "您无权分享 %s",
- "Sharing %s failed, because the user %s does not exist" : "共享 %s 失败,因为用户 %s 不存在",
- "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "共享 %s 失败,因为用户 %s 不是 %s 所属的任何组的用户",
- "Sharing %s failed, because this item is already shared with %s" : "共享 %s 失败,因为它已经共享给 %s",
- "Sharing %s failed, because the group %s does not exist" : "共享 %s 失败,因为 %s 组不存在",
- "Sharing %s failed, because %s is not a member of the group %s" : "共享 %s 失败,因为 %s 不是 %s 组的成员",
- "Sharing %s failed, because sharing with links is not allowed" : "共享 %s 失败,因为不允许用链接共享",
+ "Sharing %s failed, because you can not share with yourself" : "分享 %s 失败, 因为您不能分享给自己",
+ "Sharing %s failed, because the user %s does not exist" : "分享 %s 失败, 因为用户 %s 不存在",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "分享 %s 失败, 因为用户 %s 不是 %s 所属的任何组的用户",
+ "Sharing %s failed, because this item is already shared with %s" : "分享 %s 失败, 因为该项已经分享给用户 %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "分享 %s 失败, 因为该项已经分享给用户 %s",
+ "Sharing %s failed, because the group %s does not exist" : "分享 %s 失败, 因为 %s 分组不存在",
+ "Sharing %s failed, because %s is not a member of the group %s" : "分享 %s 失败, 因为 %s 不是 %s 分组的成员",
+ "You need to provide a password to create a public link, only protected links are allowed" : "链接分享需要密码, 您需要提供一个密码以创建公开连接",
+ "Sharing %s failed, because sharing with links is not allowed" : "分享 %s 失败, 因为不允许使用链接分享",
"Not allowed to create a federated share with the same user" : "不能给你自己分享文件",
- "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "文件:%s 分享失败,联合云无法找到 %s,请检查设置或联系管理员。",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "分享 %s 失败, 无法找到 %s, 该服务当前无法连接.",
"Share type %s is not valid for %s" : "%s 不是 %s 的合法共享类型",
"Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "设置 %s 权限失败,因为权限超出了 %s 已有权限。",
"Setting permissions for %s failed, because the item was not found" : "设置 %s 的权限失败,因为未找到到对应项",
- "Sharing backend %s must implement the interface OCP\\Share_Backend" : "共享后端 %s 必须实现 OCP\\Share_Backend 接口",
- "Sharing backend %s not found" : "未找到共享后端 %s",
- "Sharing backend for %s not found" : "%s 的共享后端未找到",
- "Sharing %s failed, because the permissions exceed permissions granted to %s" : "共享 %s 失败,因为权限超过了 %s 已有权限",
- "Sharing %s failed, because resharing is not allowed" : "共享 %s 失败,因为不允许二次共享",
- "Sharing %s failed, because the sharing backend for %s could not find its source" : "共享 %s 失败,因为 %s 使用的共享后端未找到它的来源",
- "Sharing %s failed, because the file could not be found in the file cache" : "共享 %s 失败,因为未在文件缓存中找到文件。",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "无法设置过期时间. 过期时间不能晚于其分享时间 %s",
+ "Cannot set expiration date. Expiration date is in the past" : "无法设置过期时间. 过期时间不能为过去",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "无法清除过期时间. 每个分享必须有一个过期时间",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "分享后端 %s 必须实现 OCP\\Share_Backend 接口",
+ "Sharing backend %s not found" : "%s 的分享后端未找到",
+ "Sharing backend for %s not found" : "%s 的分享后端未找到",
+ "Sharing failed, because the user %s is the original sharer" : "分享失败, 因为用户 %s 是原始的分享者.",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "分享 %s 失败, 因为权限超过了 %s 的已有权限",
+ "Sharing %s failed, because resharing is not allowed" : "分享 %s 失败, 因为不允许二次共享",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "分享 %s 失败, 因为无法找到 %s 分享后端的来源",
+ "Sharing %s failed, because the file could not be found in the file cache" : "分享 %s 失败, 因为文件缓存中找不到该文件",
"Cannot increase permissions of %s" : "无法提升 %s 的权限",
+ "Files can't be shared with delete permissions" : "无法分享有删除权限的文件",
+ "Files can't be shared with create permissions" : "无法分享有创建权限的文件",
"Expiration date is in the past" : "到期日期已过.",
"Cannot set expiration date more than %s days in the future" : "无法将过期日期设置为超过 %s 天.",
"Could not find category \"%s\"" : "无法找到分类 \"%s\"",
@@ -102,13 +118,13 @@ OC.L10N.register(
"Thu." : "周四",
"Fri." : "周五",
"Sat." : "周六",
- "Su" : "日",
- "Mo" : "一",
+ "Su" : "日",
+ "Mo" : "一",
"Tu" : "二",
- "We" : "三",
+ "We" : "三",
"Th" : "四",
"Fr" : "五",
- "Sa" : "六",
+ "Sa" : "六",
"January" : "一月",
"February" : "二月",
"March" : "三月",
@@ -150,6 +166,7 @@ OC.L10N.register(
"No app name specified" : "没有指定的 App 名称",
"App '%s' could not be installed!" : "应用程序 '%s' 无法被安装!",
"App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "应用程序 \"%s\" 无法被安装,因为为满足下列依赖关系: %s",
+ "a safe home for all your data" : "给您所有的数据一个安全的家",
"File is currently busy, please try again later" : "文件当前正忙,请稍后再试",
"Can't read file" : "无法读取文件",
"Application is not enabled" : "应用程序未启用",
@@ -159,7 +176,10 @@ OC.L10N.register(
"No database drivers (sqlite, mysql, or postgresql) installed." : "没有安装数据库驱动 (SQLite、MySQL 或 PostgreSQL)。",
"Cannot write into \"config\" directory" : "无法写入“config”目录",
"Cannot write into \"apps\" directory" : "无法写入“apps”目录",
+ "This can usually be fixed by %sgiving the webserver write access to the apps directory%s or disabling the appstore in the config file." : "您可以由 %s 设置 Web 服务器对应用目录 %s 的写权限或在配置文件中禁用应用商店可以修复这个问题.",
"Cannot create \"data\" directory (%s)" : "无法创建“apps”目录 (%s)",
+ "This can usually be fixed by <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">giving the webserver write access to the root directory</a>." : "点击 <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">设置 Web 服务器对根目录的写入权限</a> 可修复这个问题.",
+ "Permissions can usually be fixed by %sgiving the webserver write access to the root directory%s." : "您可以由 %s 设置 Web 服务器对根目录 %s 的写权限可以修复这个问题.",
"Setting locale to %s failed" : "设置语言为 %s 失败",
"Please install one of these locales on your system and restart your webserver." : "请在您的系统中安装下述一种语言并重启 Web 服务器.",
"Please ask your server administrator to install the module." : "请联系服务器管理员安装模块.",
@@ -170,6 +190,7 @@ OC.L10N.register(
"To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "请在 php.ini 中设置 <code>mbstring.func_overload</code> 为 <code>0</code> 以解决该问题",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "至少需要 libxml2 2.7.0. 当前安装 %s.",
"To fix this issue update your libxml2 version and restart your web server." : "升级您的 libxml2 版本然后重启 Web 服务器以解决该问题.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP 被设置为移除内联块, 这将导致多个核心应用无法访问.",
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "这可能由缓存/加速器导致的, 例如 Zend OPcache 或 eAccelerator.",
"PHP modules have been installed, but they are still listed as missing?" : "PHP 模块已经安装, 但仍然显示未安装?",
"Please ask your server administrator to restart the web server." : "请联系服务器管理员重启 Web 服务器.",
diff --git a/lib/l10n/zh_CN.json b/lib/l10n/zh_CN.json
index 0bcf8862f1a..f5b88f87ad9 100644
--- a/lib/l10n/zh_CN.json
+++ b/lib/l10n/zh_CN.json
@@ -1,18 +1,23 @@
{ "translations": {
"Cannot write into \"config\" directory!" : "无法写入 \"config\" 目录!",
- "This can usually be fixed by giving the webserver write access to the config directory" : "对 Web 服务器设置 config 目录的写权限可以修复这个问题.",
+ "This can usually be fixed by giving the webserver write access to the config directory" : "您可以设置 Web 服务器对 config 目录的写权限修复这个问题",
"See %s" : "查看 %s",
- "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "对 Web 服务器%s设置 config 目录%s的写权限可以修复这个问题.",
+ "This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "您可以由 %s 设置 Web 服务器对 config 目录 %s 的写权限修复这个问题",
+ "The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server." : "应用 %$1s 的文件替换不正确. 请确认版本与当前服务器兼容.",
"Sample configuration detected" : "示例配置检测",
+ "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "您似乎直接把 config.php 的样例文件直接复制使用. 这可能会破坏您的安装. 在对 config.php 进行修改之前请先阅读相关文档.",
"%1$s and %2$s" : "%1$s 和 %2$s",
"%1$s, %2$s and %3$s" : "%1$s, %2$s 和 %3$s",
"%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s 和 %4$s",
"%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s 和 %5$s",
"PHP %s or higher is required." : "要求 PHP 版本 %s 或者更高。",
"PHP with a version lower than %s is required." : "需要版本低于 %s 的PHP.",
+ "%sbit or higher PHP required." : "需要 %s 或更高版本的 PHP",
"Following databases are supported: %s" : "支持以下数据库: %s",
"The command line tool %s could not be found" : "命令行工具 %s 未找到",
"The library %s is not available." : "库文件 %s 不可用",
+ "Library %s with a version higher than %s is required - available version %s." : "%s 需要 %s 或更高的版本 - 可用版本 %s.",
+ "Library %s with a version lower than %s is required - available version %s." : "%s 需要 %s 或更低的版本 - 可用版本 %s.",
"Following platforms are supported: %s" : "支持以下平台:%s",
"Server version %s or higher is required." : "需要服务器版本 %s 或更高版本。",
"Server version %s or lower is required." : "需要服务器版本 %s 或更低版本。",
@@ -29,6 +34,7 @@
"_%n hour ago_::_%n hours ago_" : ["%n 小时前"],
"_%n minute ago_::_%n minutes ago_" : ["%n 分钟前"],
"seconds ago" : "秒前",
+ "Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID 为 %s 的模块不存在. 请在应用设置中启用或联系您的管理员.",
"File name is a reserved word" : "文件名包含敏感字符",
"File name contains at least one invalid character" : "文件名中存在至少一个非法字符",
"File name is too long" : "文件名过长",
@@ -62,27 +68,37 @@
"Invalid Federated Cloud ID" : "无效的联合云ID",
"%s shared »%s« with you" : "%s 向您分享了 »%s«",
"%s via %s" : "%s 通过 %s",
- "Sharing %s failed, because the file does not exist" : "共享 %s 失败,因为文件不存在。",
+ "Sharing %s failed, because the backend does not allow shares from type %i" : "分享 %s 失败, 因为后端不允许分享 %i 类型",
+ "Sharing %s failed, because the file does not exist" : "分享 %s 失败, 因为文件不存在.",
"You are not allowed to share %s" : "您无权分享 %s",
- "Sharing %s failed, because the user %s does not exist" : "共享 %s 失败,因为用户 %s 不存在",
- "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "共享 %s 失败,因为用户 %s 不是 %s 所属的任何组的用户",
- "Sharing %s failed, because this item is already shared with %s" : "共享 %s 失败,因为它已经共享给 %s",
- "Sharing %s failed, because the group %s does not exist" : "共享 %s 失败,因为 %s 组不存在",
- "Sharing %s failed, because %s is not a member of the group %s" : "共享 %s 失败,因为 %s 不是 %s 组的成员",
- "Sharing %s failed, because sharing with links is not allowed" : "共享 %s 失败,因为不允许用链接共享",
+ "Sharing %s failed, because you can not share with yourself" : "分享 %s 失败, 因为您不能分享给自己",
+ "Sharing %s failed, because the user %s does not exist" : "分享 %s 失败, 因为用户 %s 不存在",
+ "Sharing %s failed, because the user %s is not a member of any groups that %s is a member of" : "分享 %s 失败, 因为用户 %s 不是 %s 所属的任何组的用户",
+ "Sharing %s failed, because this item is already shared with %s" : "分享 %s 失败, 因为该项已经分享给用户 %s",
+ "Sharing %s failed, because this item is already shared with user %s" : "分享 %s 失败, 因为该项已经分享给用户 %s",
+ "Sharing %s failed, because the group %s does not exist" : "分享 %s 失败, 因为 %s 分组不存在",
+ "Sharing %s failed, because %s is not a member of the group %s" : "分享 %s 失败, 因为 %s 不是 %s 分组的成员",
+ "You need to provide a password to create a public link, only protected links are allowed" : "链接分享需要密码, 您需要提供一个密码以创建公开连接",
+ "Sharing %s failed, because sharing with links is not allowed" : "分享 %s 失败, 因为不允许使用链接分享",
"Not allowed to create a federated share with the same user" : "不能给你自己分享文件",
- "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "文件:%s 分享失败,联合云无法找到 %s,请检查设置或联系管理员。",
+ "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "分享 %s 失败, 无法找到 %s, 该服务当前无法连接.",
"Share type %s is not valid for %s" : "%s 不是 %s 的合法共享类型",
"Setting permissions for %s failed, because the permissions exceed permissions granted to %s" : "设置 %s 权限失败,因为权限超出了 %s 已有权限。",
"Setting permissions for %s failed, because the item was not found" : "设置 %s 的权限失败,因为未找到到对应项",
- "Sharing backend %s must implement the interface OCP\\Share_Backend" : "共享后端 %s 必须实现 OCP\\Share_Backend 接口",
- "Sharing backend %s not found" : "未找到共享后端 %s",
- "Sharing backend for %s not found" : "%s 的共享后端未找到",
- "Sharing %s failed, because the permissions exceed permissions granted to %s" : "共享 %s 失败,因为权限超过了 %s 已有权限",
- "Sharing %s failed, because resharing is not allowed" : "共享 %s 失败,因为不允许二次共享",
- "Sharing %s failed, because the sharing backend for %s could not find its source" : "共享 %s 失败,因为 %s 使用的共享后端未找到它的来源",
- "Sharing %s failed, because the file could not be found in the file cache" : "共享 %s 失败,因为未在文件缓存中找到文件。",
+ "Cannot set expiration date. Shares cannot expire later than %s after they have been shared" : "无法设置过期时间. 过期时间不能晚于其分享时间 %s",
+ "Cannot set expiration date. Expiration date is in the past" : "无法设置过期时间. 过期时间不能为过去",
+ "Cannot clear expiration date. Shares are required to have an expiration date." : "无法清除过期时间. 每个分享必须有一个过期时间",
+ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "分享后端 %s 必须实现 OCP\\Share_Backend 接口",
+ "Sharing backend %s not found" : "%s 的分享后端未找到",
+ "Sharing backend for %s not found" : "%s 的分享后端未找到",
+ "Sharing failed, because the user %s is the original sharer" : "分享失败, 因为用户 %s 是原始的分享者.",
+ "Sharing %s failed, because the permissions exceed permissions granted to %s" : "分享 %s 失败, 因为权限超过了 %s 的已有权限",
+ "Sharing %s failed, because resharing is not allowed" : "分享 %s 失败, 因为不允许二次共享",
+ "Sharing %s failed, because the sharing backend for %s could not find its source" : "分享 %s 失败, 因为无法找到 %s 分享后端的来源",
+ "Sharing %s failed, because the file could not be found in the file cache" : "分享 %s 失败, 因为文件缓存中找不到该文件",
"Cannot increase permissions of %s" : "无法提升 %s 的权限",
+ "Files can't be shared with delete permissions" : "无法分享有删除权限的文件",
+ "Files can't be shared with create permissions" : "无法分享有创建权限的文件",
"Expiration date is in the past" : "到期日期已过.",
"Cannot set expiration date more than %s days in the future" : "无法将过期日期设置为超过 %s 天.",
"Could not find category \"%s\"" : "无法找到分类 \"%s\"",
@@ -100,13 +116,13 @@
"Thu." : "周四",
"Fri." : "周五",
"Sat." : "周六",
- "Su" : "日",
- "Mo" : "一",
+ "Su" : "日",
+ "Mo" : "一",
"Tu" : "二",
- "We" : "三",
+ "We" : "三",
"Th" : "四",
"Fr" : "五",
- "Sa" : "六",
+ "Sa" : "六",
"January" : "一月",
"February" : "二月",
"March" : "三月",
@@ -148,6 +164,7 @@
"No app name specified" : "没有指定的 App 名称",
"App '%s' could not be installed!" : "应用程序 '%s' 无法被安装!",
"App \"%s\" cannot be installed because the following dependencies are not fulfilled: %s" : "应用程序 \"%s\" 无法被安装,因为为满足下列依赖关系: %s",
+ "a safe home for all your data" : "给您所有的数据一个安全的家",
"File is currently busy, please try again later" : "文件当前正忙,请稍后再试",
"Can't read file" : "无法读取文件",
"Application is not enabled" : "应用程序未启用",
@@ -157,7 +174,10 @@
"No database drivers (sqlite, mysql, or postgresql) installed." : "没有安装数据库驱动 (SQLite、MySQL 或 PostgreSQL)。",
"Cannot write into \"config\" directory" : "无法写入“config”目录",
"Cannot write into \"apps\" directory" : "无法写入“apps”目录",
+ "This can usually be fixed by %sgiving the webserver write access to the apps directory%s or disabling the appstore in the config file." : "您可以由 %s 设置 Web 服务器对应用目录 %s 的写权限或在配置文件中禁用应用商店可以修复这个问题.",
"Cannot create \"data\" directory (%s)" : "无法创建“apps”目录 (%s)",
+ "This can usually be fixed by <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">giving the webserver write access to the root directory</a>." : "点击 <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">设置 Web 服务器对根目录的写入权限</a> 可修复这个问题.",
+ "Permissions can usually be fixed by %sgiving the webserver write access to the root directory%s." : "您可以由 %s 设置 Web 服务器对根目录 %s 的写权限可以修复这个问题.",
"Setting locale to %s failed" : "设置语言为 %s 失败",
"Please install one of these locales on your system and restart your webserver." : "请在您的系统中安装下述一种语言并重启 Web 服务器.",
"Please ask your server administrator to install the module." : "请联系服务器管理员安装模块.",
@@ -168,6 +188,7 @@
"To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini" : "请在 php.ini 中设置 <code>mbstring.func_overload</code> 为 <code>0</code> 以解决该问题",
"libxml2 2.7.0 is at least required. Currently %s is installed." : "至少需要 libxml2 2.7.0. 当前安装 %s.",
"To fix this issue update your libxml2 version and restart your web server." : "升级您的 libxml2 版本然后重启 Web 服务器以解决该问题.",
+ "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP 被设置为移除内联块, 这将导致多个核心应用无法访问.",
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "这可能由缓存/加速器导致的, 例如 Zend OPcache 或 eAccelerator.",
"PHP modules have been installed, but they are still listed as missing?" : "PHP 模块已经安装, 但仍然显示未安装?",
"Please ask your server administrator to restart the web server." : "请联系服务器管理员重启 Web 服务器.",
diff --git a/lib/private/Files/Notify/Change.php b/lib/private/Files/Notify/Change.php
new file mode 100644
index 00000000000..78cc007b27d
--- /dev/null
+++ b/lib/private/Files/Notify/Change.php
@@ -0,0 +1,65 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\Notify;
+
+use OCP\Files\Notify\IChange;
+
+class Change implements IChange {
+ /** @var int */
+ private $type;
+
+ /** @var string */
+ private $path;
+
+ /**
+ * Change constructor.
+ *
+ * @param int $type
+ * @param string $path
+ */
+ public function __construct($type, $path) {
+ $this->type = $type;
+ $this->path = $path;
+ }
+
+ /**
+ * Get the type of the change
+ *
+ * @return int IChange::ADDED, IChange::REMOVED, IChange::MODIFIED or IChange::RENAMED
+ */
+ public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * Get the path of the file that was changed relative to the root of the storage
+ *
+ * Note, for rename changes this path is the old path for the file
+ *
+ * @return mixed
+ */
+ public function getPath() {
+ return $this->path;
+ }
+}
diff --git a/lib/private/Files/Notify/RenameChange.php b/lib/private/Files/Notify/RenameChange.php
new file mode 100644
index 00000000000..b83dffa0cb2
--- /dev/null
+++ b/lib/private/Files/Notify/RenameChange.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\Notify;
+
+use OCP\Files\Notify\IRenameChange;
+
+class RenameChange extends Change implements IRenameChange {
+ /** @var string */
+ private $targetPath;
+
+ /**
+ * Change constructor.
+ *
+ * @param int $type
+ * @param string $path
+ * @param string $targetPath
+ */
+ public function __construct($type, $path, $targetPath) {
+ parent::__construct($type, $path);
+ $this->targetPath = $targetPath;
+ }
+
+ /**
+ * Get the new path of the renamed file relative to the storage root
+ *
+ * @return string
+ */
+ public function getTargetPath() {
+ return $this->targetPath;
+ }
+}
diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php
index 4fe7dcafbbf..80d48680be1 100644
--- a/lib/private/Files/Storage/Local.php
+++ b/lib/private/Files/Storage/Local.php
@@ -205,18 +205,7 @@ class Local extends \OC\Files\Storage\Common {
}
public function file_get_contents($path) {
- // file_get_contents() has a memory leak: https://bugs.php.net/bug.php?id=61961
- $fileName = $this->getSourcePath($path);
-
- $fileSize = filesize($fileName);
- if ($fileSize === 0) {
- return '';
- }
-
- $handle = fopen($fileName, 'rb');
- $content = fread($handle, $fileSize);
- fclose($handle);
- return $content;
+ return file_get_contents($this->getSourcePath($path));
}
public function file_put_contents($path, $data) {
diff --git a/lib/private/Repair/MoveUpdaterStepFile.php b/lib/private/Repair/MoveUpdaterStepFile.php
index fabaff40d24..feb8a291282 100644
--- a/lib/private/Repair/MoveUpdaterStepFile.php
+++ b/lib/private/Repair/MoveUpdaterStepFile.php
@@ -44,7 +44,7 @@ class MoveUpdaterStepFile implements IRepairStep {
public function run(IOutput $output) {
- $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT);
+ $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
$instanceId = $this->config->getSystemValue('instanceid', null);
if(!is_string($instanceId) || empty($instanceId)) {
diff --git a/lib/private/Setup/Sqlite.php b/lib/private/Setup/Sqlite.php
index 63b970be42e..4d860103b60 100644
--- a/lib/private/Setup/Sqlite.php
+++ b/lib/private/Setup/Sqlite.php
@@ -33,7 +33,7 @@ class Sqlite extends AbstractDatabase {
}
public function setupDatabase($username) {
- $datadir = \OC::$server->getSystemConfig()->getValue('datadirectory');
+ $datadir = \OC::$server->getSystemConfig()->getValue('datadirectory', \OC::$SERVERROOT . '/data');
//delete the old sqlite database first, might cause infinte loops otherwise
if(file_exists("$datadir/owncloud.db")) {
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 4b37efe0705..c37bb59028e 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -267,7 +267,7 @@ class User implements IUser {
if ($this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {
$this->home = $home;
} elseif ($this->config) {
- $this->home = $this->config->getSystemValue('datadirectory') . '/' . $this->uid;
+ $this->home = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $this->uid;
} else {
$this->home = \OC::$SERVERROOT . '/data/' . $this->uid;
}
diff --git a/lib/public/Files/Notify/IChange.php b/lib/public/Files/Notify/IChange.php
new file mode 100644
index 00000000000..1e6aaa8abe0
--- /dev/null
+++ b/lib/public/Files/Notify/IChange.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Notify;
+
+/**
+ * Represents a detected change in the storage
+ *
+ * @since 12.0.0
+ */
+interface IChange {
+ const ADDED = 1;
+ const REMOVED = 2;
+ const MODIFIED = 3;
+ const RENAMED = 4;
+
+ /**
+ * Get the type of the change
+ *
+ * @return int IChange::ADDED, IChange::REMOVED, IChange::MODIFIED or IChange::RENAMED
+ *
+ * @since 12.0.0
+ */
+ public function getType();
+
+ /**
+ * Get the path of the file that was changed relative to the root of the storage
+ *
+ * Note, for rename changes this path is the old path for the file
+ *
+ * @return mixed
+ *
+ * @since 12.0.0
+ */
+ public function getPath();
+}
diff --git a/lib/public/Files/Notify/INotifyHandler.php b/lib/public/Files/Notify/INotifyHandler.php
new file mode 100644
index 00000000000..7e0e6a610d8
--- /dev/null
+++ b/lib/public/Files/Notify/INotifyHandler.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Notify;
+
+/**
+ * Provides access to detected changes in the storage by either actively listening
+ * or getting the list of changes that happened in the background
+ *
+ * @since 12.0.0
+ */
+interface INotifyHandler {
+ /**
+ * Start listening for update notifications
+ *
+ * The provided callback will be called for every incoming notification with the following parameters
+ * - IChange|IRenameChange $change
+ *
+ * Note that this call is blocking and will not exit on it's own, to stop listening for notifications return `false` from the callback
+ *
+ * @param callable $callback
+ *
+ * @since 12.0.0
+ */
+ public function listen(callable $callback);
+
+ /**
+ * Get all changes detected since the start of the notify process or the last call to getChanges
+ *
+ * @return IChange[]
+ *
+ * @since 12.0.0
+ */
+ public function getChanges();
+
+ /**
+ * Stop listening for changes
+ *
+ * Note that any pending changes will be discarded
+ *
+ * @since 12.0.0
+ */
+ public function stop();
+}
diff --git a/lib/public/Files/Notify/IRenameChange.php b/lib/public/Files/Notify/IRenameChange.php
new file mode 100644
index 00000000000..c95499a7e74
--- /dev/null
+++ b/lib/public/Files/Notify/IRenameChange.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
+ *
+ * @author Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\Files\Notify;
+
+/**
+ * Represents a detected rename change
+ *
+ * @since 12.0.0
+ */
+interface IRenameChange extends IChange {
+ /**
+ * Get the new path of the renamed file relative to the storage root
+ *
+ * @return string
+ *
+ * @since 12.0.0
+ */
+ public function getTargetPath();
+}
diff --git a/lib/public/Files/Storage/INotifyStorage.php b/lib/public/Files/Storage/INotifyStorage.php
index e99124abdfd..c6fdd44724f 100644
--- a/lib/public/Files/Storage/INotifyStorage.php
+++ b/lib/public/Files/Storage/INotifyStorage.php
@@ -23,6 +23,8 @@
namespace OCP\Files\Storage;
+use OCP\Files\Notify\INotifyHandler;
+
/**
* Storage backend that support active notifications
*
@@ -48,6 +50,17 @@ interface INotifyStorage {
* @param callable $callback
*
* @since 9.1.0
+ * @deprecated 12.0.0 use INotifyStorage::notify()->listen() instead
*/
public function listen($path, callable $callback);
+
+ /**
+ * Start the notification handler for this storage
+ *
+ * @param $path
+ * @return INotifyHandler
+ *
+ * @since 12.0.0
+ */
+ public function notify($path);
}
diff --git a/settings/l10n/sv.js b/settings/l10n/sv.js
index 803021a8d31..964c65427cd 100644
--- a/settings/l10n/sv.js
+++ b/settings/l10n/sv.js
@@ -203,7 +203,7 @@ OC.L10N.register(
"To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "För att köra detta behöver du PHP posix tillägget. Se {linkstart}PHP dokumentationen{linkend} för ytterligare detaljer.",
"Version" : "Version",
"Sharing" : "Dela",
- "Allow apps to use the Share API" : "Tillåt applikationer att använda delat API",
+ "Allow apps to use the Share API" : "Tillåt applikationer att använda API för delning",
"Allow users to share via link" : "Tillåt användare att dela via länk",
"Allow public uploads" : "Tillåt offentlig uppladdning",
"Enforce password protection" : "Tillämpa lösenordskydd",
diff --git a/settings/l10n/sv.json b/settings/l10n/sv.json
index 4024d1b622a..8bfa6e9b38e 100644
--- a/settings/l10n/sv.json
+++ b/settings/l10n/sv.json
@@ -201,7 +201,7 @@
"To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "För att köra detta behöver du PHP posix tillägget. Se {linkstart}PHP dokumentationen{linkend} för ytterligare detaljer.",
"Version" : "Version",
"Sharing" : "Dela",
- "Allow apps to use the Share API" : "Tillåt applikationer att använda delat API",
+ "Allow apps to use the Share API" : "Tillåt applikationer att använda API för delning",
"Allow users to share via link" : "Tillåt användare att dela via länk",
"Allow public uploads" : "Tillåt offentlig uppladdning",
"Enforce password protection" : "Tillämpa lösenordskydd",
diff --git a/settings/l10n/zh_CN.js b/settings/l10n/zh_CN.js
index e7edc0dd002..9392b2d92e1 100644
--- a/settings/l10n/zh_CN.js
+++ b/settings/l10n/zh_CN.js
@@ -229,7 +229,7 @@ OC.L10N.register(
"How to do backups" : "如何备份",
"Advanced monitoring" : "高级监控",
"Performance tuning" : "性能优化",
- "Improving the config.php" : "正在优化 config.php",
+ "Improving the config.php" : "优化 config.php",
"Theming" : "主题",
"Hardening and security guidance" : "强化和安全指南",
"Developer documentation" : "开发者文档",
diff --git a/settings/l10n/zh_CN.json b/settings/l10n/zh_CN.json
index 4e0f050f3c4..46079a83ceb 100644
--- a/settings/l10n/zh_CN.json
+++ b/settings/l10n/zh_CN.json
@@ -227,7 +227,7 @@
"How to do backups" : "如何备份",
"Advanced monitoring" : "高级监控",
"Performance tuning" : "性能优化",
- "Improving the config.php" : "正在优化 config.php",
+ "Improving the config.php" : "优化 config.php",
"Theming" : "主题",
"Hardening and security guidance" : "强化和安全指南",
"Developer documentation" : "开发者文档",