aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/encryption/appinfo/application.php3
-rw-r--r--apps/encryption/controller/settingscontroller.php16
-rw-r--r--apps/encryption/l10n/el.js3
-rw-r--r--apps/encryption/l10n/el.json3
-rw-r--r--apps/encryption/l10n/id.js3
-rw-r--r--apps/encryption/l10n/id.json3
-rw-r--r--apps/encryption/l10n/nl.js3
-rw-r--r--apps/encryption/l10n/nl.json3
-rw-r--r--apps/encryption/l10n/tr.js3
-rw-r--r--apps/encryption/l10n/tr.json3
-rw-r--r--apps/encryption/lib/crypto/crypt.php2
-rw-r--r--apps/encryption/tests/controller/SettingsControllerTest.php32
-rw-r--r--apps/encryption/tests/lib/crypto/cryptTest.php15
-rw-r--r--apps/files/css/detailsView.css36
-rw-r--r--apps/files/css/files.css1
-rw-r--r--apps/files/js/detailsview.js17
-rw-r--r--apps/files/js/fileinfomodel.js9
-rw-r--r--apps/files/js/filelist.js13
-rw-r--r--apps/files/js/mainfileinfodetailview.js65
-rw-r--r--apps/files/l10n/tr.js3
-rw-r--r--apps/files/l10n/tr.json3
-rw-r--r--apps/files/l10n/zh_CN.js3
-rw-r--r--apps/files/l10n/zh_CN.json3
-rw-r--r--apps/files/l10n/zh_TW.js4
-rw-r--r--apps/files/l10n/zh_TW.json4
-rw-r--r--apps/files/tests/js/mainfileinfodetailviewSpec.js8
-rw-r--r--apps/files_external/l10n/id.js22
-rw-r--r--apps/files_external/l10n/id.json22
-rw-r--r--apps/files_external/l10n/it.js1
-rw-r--r--apps/files_external/l10n/it.json1
-rw-r--r--apps/files_external/l10n/nl.js8
-rw-r--r--apps/files_external/l10n/nl.json8
-rw-r--r--apps/files_external/l10n/tr.js22
-rw-r--r--apps/files_external/l10n/tr.json22
-rw-r--r--apps/files_external/lib/google.php2
-rw-r--r--apps/files_external/service/storagesservice.php4
-rw-r--r--apps/files_external/tests/service/globalstoragesservicetest.php28
-rw-r--r--apps/files_external/tests/service/userglobalstoragesservicetest.php5
-rw-r--r--apps/files_sharing/api/local.php4
-rw-r--r--apps/files_sharing/api/sharees.php409
-rw-r--r--apps/files_sharing/appinfo/routes.php13
-rw-r--r--apps/files_sharing/tests/api.php138
-rw-r--r--apps/files_sharing/tests/api/shareestest.php995
-rw-r--r--apps/user_ldap/l10n/tr.js12
-rw-r--r--apps/user_ldap/l10n/tr.json12
-rwxr-xr-xautotest-external.sh6
-rwxr-xr-xautotest.sh6
-rw-r--r--core/ajax/preview.php2
-rw-r--r--core/command/encryption/changekeystorageroot.php270
-rw-r--r--core/command/encryption/showkeystorageroot.php58
-rw-r--r--core/css/apps.css5
-rw-r--r--core/js/tests/specs/appsSpec.js48
-rw-r--r--core/l10n/fr.js2
-rw-r--r--core/l10n/fr.json2
-rw-r--r--core/l10n/hu_HU.js2
-rw-r--r--core/l10n/hu_HU.json2
-rw-r--r--core/l10n/id.js3
-rw-r--r--core/l10n/id.json3
-rw-r--r--core/l10n/tr.js18
-rw-r--r--core/l10n/tr.json18
-rw-r--r--core/l10n/zh_CN.js17
-rw-r--r--core/l10n/zh_CN.json17
-rw-r--r--core/l10n/zh_TW.js2
-rw-r--r--core/l10n/zh_TW.json2
-rw-r--r--core/register_command.php17
-rw-r--r--lib/autoloader.php33
-rw-r--r--lib/base.php19
-rw-r--r--lib/l10n/id.js1
-rw-r--r--lib/l10n/id.json1
-rw-r--r--lib/private/activitymanager.php14
-rw-r--r--lib/private/appframework/http.php2
-rw-r--r--lib/private/appframework/http/request.php83
-rw-r--r--lib/private/encryption/keys/storage.php25
-rw-r--r--lib/private/encryption/manager.php53
-rw-r--r--lib/private/encryption/util.php42
-rw-r--r--lib/private/files/storage/storagefactory.php3
-rw-r--r--lib/private/preview.php74
-rw-r--r--lib/private/route/router.php5
-rw-r--r--lib/private/security/certificatemanager.php15
-rw-r--r--lib/private/server.php27
-rw-r--r--lib/private/util.php1
-rw-r--r--settings/controller/checksetupcontroller.php2
-rw-r--r--settings/l10n/hu_HU.js6
-rw-r--r--settings/l10n/hu_HU.json6
-rw-r--r--settings/l10n/id.js7
-rw-r--r--settings/l10n/id.json7
-rw-r--r--settings/l10n/it.js2
-rw-r--r--settings/l10n/it.json2
-rw-r--r--settings/l10n/tr.js13
-rw-r--r--settings/l10n/tr.json13
-rw-r--r--settings/l10n/zh_CN.js89
-rw-r--r--settings/l10n/zh_CN.json89
-rw-r--r--settings/languageCodes.php1
-rw-r--r--tests/bootstrap.php2
-rw-r--r--tests/core/command/encryption/changekeystorageroottest.php381
-rw-r--r--tests/lib/appframework/http/HttpTest.php8
-rw-r--r--tests/lib/autoloader.php2
-rw-r--r--tests/lib/encryption/keys/storage.php59
-rw-r--r--tests/lib/encryption/managertest.php10
-rw-r--r--tests/lib/encryption/utiltest.php19
-rw-r--r--tests/lib/security/certificatemanager.php6
-rw-r--r--tests/lib/template.php72
-rw-r--r--tests/settings/controller/CheckSetupControllerTest.php28
103 files changed, 3511 insertions, 200 deletions
diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php
index cba8964eefb..75107b2723c 100644
--- a/apps/encryption/appinfo/application.php
+++ b/apps/encryption/appinfo/application.php
@@ -198,7 +198,8 @@ class Application extends \OCP\AppFramework\App {
$server->getUserSession(),
$c->query('KeyManager'),
$c->query('Crypt'),
- $c->query('Session')
+ $c->query('Session'),
+ $server->getSession()
);
});
diff --git a/apps/encryption/controller/settingscontroller.php b/apps/encryption/controller/settingscontroller.php
index 2a668f7cd4a..8e6de19e784 100644
--- a/apps/encryption/controller/settingscontroller.php
+++ b/apps/encryption/controller/settingscontroller.php
@@ -31,6 +31,7 @@ use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IL10N;
use OCP\IRequest;
+use OCP\ISession;
use OCP\IUserManager;
use OCP\IUserSession;
@@ -54,6 +55,9 @@ class SettingsController extends Controller {
/** @var Session */
private $session;
+ /** @var ISession */
+ private $ocSession;
+
/**
* @param string $AppName
* @param IRequest $request
@@ -63,6 +67,7 @@ class SettingsController extends Controller {
* @param KeyManager $keyManager
* @param Crypt $crypt
* @param Session $session
+ * @param ISession $ocSession
*/
public function __construct($AppName,
IRequest $request,
@@ -71,7 +76,8 @@ class SettingsController extends Controller {
IUserSession $userSession,
KeyManager $keyManager,
Crypt $crypt,
- Session $session) {
+ Session $session,
+ ISession $ocSession) {
parent::__construct($AppName, $request);
$this->l = $l10n;
$this->userSession = $userSession;
@@ -79,6 +85,7 @@ class SettingsController extends Controller {
$this->keyManager = $keyManager;
$this->crypt = $crypt;
$this->session = $session;
+ $this->ocSession = $ocSession;
}
@@ -97,6 +104,13 @@ class SettingsController extends Controller {
//check if password is correct
$passwordCorrect = $this->userManager->checkPassword($uid, $newPassword);
+ if ($passwordCorrect === false) {
+ // if check with uid fails we need to check the password with the login name
+ // e.g. in the ldap case. For local user we need to check the password with
+ // the uid because in this case the login name is case insensitive
+ $loginName = $this->ocSession->get('loginname');
+ $passwordCorrect = $this->userManager->checkPassword($loginName, $newPassword);
+ }
if ($passwordCorrect !== false) {
$encryptedKey = $this->keyManager->getPrivateKey($uid);
diff --git a/apps/encryption/l10n/el.js b/apps/encryption/l10n/el.js
index 1c9178831b6..d27098ddb04 100644
--- a/apps/encryption/l10n/el.js
+++ b/apps/encryption/l10n/el.js
@@ -25,10 +25,13 @@ OC.L10N.register(
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Άκυρο προσωπικό κλειδί για την εφαρμογή κρυπτογράφησης. Παρακαλώ ενημερώστε τον κωδικό του προσωπικού κλειδίου σας στις προσωπικές ρυθμίσεις για να επανακτήσετε πρόσβαση στα κρυπτογραφημένα σας αρχεία.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Η εφαρμογή κρυπτογράφησης είναι ενεργοποιημένη αλλά τα κλειδιά σας δεν έχουν καταγραφεί, παρακαλώ αποσυνδεθείτε και επανασυνδεθείτε.",
"Encryption App is enabled and ready" : "Η Εφαρμογή Κρυπτογράφησης είναι ενεργοποιημένη και έτοιμη.",
+ "one-time password for server-side-encryption" : "κωδικός μιας χρήσης για κρυπτογράφηση στο διακομιστή",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Δεν ήταν δυνατό να αποκρυπτογραφηθεί αυτό το αρχείο, πιθανόν πρόκειται για κοινόχρηστο αρχείο. Παρακαλώ ζητήστε από τον ιδιοκτήτη του αρχείου να το ξαναμοιραστεί μαζί σας.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Αδυναμία ανάγνωσης αυτού του αρχείου, πιθανό να είναι διαμοιραζόμενο αρχείο. Παρακαλώ ρωτήστε τον κάτοχο του αρχείου να το διαμοιράσει ξανά μαζί σας.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Χαίρετε,\n\nο διαχειριστής ενεργοποίηση την κρυπτογράφηση στο διακομιστή. Τα αρχεία σας κρυπτογραφήθηκαν με τον κωδικό '%s'.\n\nΠαρακαλούμε συνδεθείτε στη διεπαφή ιστού, πηγαίνετε στην ενότητα 'μονάδα βασικής κρυπτογράφησης ownCloud' στις προσωπικές σας ρυθμίσεις και ενημερώστε τον κωδικό κρυπτογράφησης εισάγοντας αυτό τον κωδικό στο πεδίο 'παλιός κωδικός σύνδεσης' και τον τωρινό σας κωδικό σύνδεσης.\n",
"The share will expire on %s." : "Ο διαμοιρασμός θα λήξει σε %s.",
"Cheers!" : "Χαιρετισμούς!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Χαίρετε,<br><br>ο διαχειριστής ενεργοποίησε την κρυπτογράφηση στο διακομιστή. Τα αρχεία σας κρυπτογραφήθηκαν με τον κωδικό <strong>%s</strong>.<br><br>Παρακαλούμε συνδεθείτε στη διεπαφή ιστού, πηγαίνετε στην ενότητα \"μονάδα βασικής κρυπτογράφησης ownCloud\" τωνπ ροσωπικών σας ρυθμίσεων και ενημερώστε τον κωδικό κρυπτογράφησης εισάγοντας αυτό τον κωδικό στο πεδίο \"παλιός κωδικός σύνδεσης\" και τον τωρινό σας κωδικό σύνδεσης.",
"Enable recovery key" : "Ενεργοποίηση κλειδιού ανάκτησης",
"Disable recovery key" : "Απενεργοποίηση κλειδιού ανάκτησης",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Το κλειδί ανάκτησης είναι ένα επιπλέον κλειδί κρυπτογράφησης που χρησιμοποιείται για να κρυπτογραφήσει αρχεία. Επιτρέπει την ανάκτηση των αρχείων ενός χρήστη αν αυτός/αυτή ξεχάσει τον κωδικό πρόσβασης.",
diff --git a/apps/encryption/l10n/el.json b/apps/encryption/l10n/el.json
index 1fdf329d852..3ed5e39b7c0 100644
--- a/apps/encryption/l10n/el.json
+++ b/apps/encryption/l10n/el.json
@@ -23,10 +23,13 @@
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Άκυρο προσωπικό κλειδί για την εφαρμογή κρυπτογράφησης. Παρακαλώ ενημερώστε τον κωδικό του προσωπικού κλειδίου σας στις προσωπικές ρυθμίσεις για να επανακτήσετε πρόσβαση στα κρυπτογραφημένα σας αρχεία.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Η εφαρμογή κρυπτογράφησης είναι ενεργοποιημένη αλλά τα κλειδιά σας δεν έχουν καταγραφεί, παρακαλώ αποσυνδεθείτε και επανασυνδεθείτε.",
"Encryption App is enabled and ready" : "Η Εφαρμογή Κρυπτογράφησης είναι ενεργοποιημένη και έτοιμη.",
+ "one-time password for server-side-encryption" : "κωδικός μιας χρήσης για κρυπτογράφηση στο διακομιστή",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Δεν ήταν δυνατό να αποκρυπτογραφηθεί αυτό το αρχείο, πιθανόν πρόκειται για κοινόχρηστο αρχείο. Παρακαλώ ζητήστε από τον ιδιοκτήτη του αρχείου να το ξαναμοιραστεί μαζί σας.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Αδυναμία ανάγνωσης αυτού του αρχείου, πιθανό να είναι διαμοιραζόμενο αρχείο. Παρακαλώ ρωτήστε τον κάτοχο του αρχείου να το διαμοιράσει ξανά μαζί σας.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Χαίρετε,\n\nο διαχειριστής ενεργοποίηση την κρυπτογράφηση στο διακομιστή. Τα αρχεία σας κρυπτογραφήθηκαν με τον κωδικό '%s'.\n\nΠαρακαλούμε συνδεθείτε στη διεπαφή ιστού, πηγαίνετε στην ενότητα 'μονάδα βασικής κρυπτογράφησης ownCloud' στις προσωπικές σας ρυθμίσεις και ενημερώστε τον κωδικό κρυπτογράφησης εισάγοντας αυτό τον κωδικό στο πεδίο 'παλιός κωδικός σύνδεσης' και τον τωρινό σας κωδικό σύνδεσης.\n",
"The share will expire on %s." : "Ο διαμοιρασμός θα λήξει σε %s.",
"Cheers!" : "Χαιρετισμούς!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Χαίρετε,<br><br>ο διαχειριστής ενεργοποίησε την κρυπτογράφηση στο διακομιστή. Τα αρχεία σας κρυπτογραφήθηκαν με τον κωδικό <strong>%s</strong>.<br><br>Παρακαλούμε συνδεθείτε στη διεπαφή ιστού, πηγαίνετε στην ενότητα \"μονάδα βασικής κρυπτογράφησης ownCloud\" τωνπ ροσωπικών σας ρυθμίσεων και ενημερώστε τον κωδικό κρυπτογράφησης εισάγοντας αυτό τον κωδικό στο πεδίο \"παλιός κωδικός σύνδεσης\" και τον τωρινό σας κωδικό σύνδεσης.",
"Enable recovery key" : "Ενεργοποίηση κλειδιού ανάκτησης",
"Disable recovery key" : "Απενεργοποίηση κλειδιού ανάκτησης",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Το κλειδί ανάκτησης είναι ένα επιπλέον κλειδί κρυπτογράφησης που χρησιμοποιείται για να κρυπτογραφήσει αρχεία. Επιτρέπει την ανάκτηση των αρχείων ενός χρήστη αν αυτός/αυτή ξεχάσει τον κωδικό πρόσβασης.",
diff --git a/apps/encryption/l10n/id.js b/apps/encryption/l10n/id.js
index c0eb1576f11..1247b35bad6 100644
--- a/apps/encryption/l10n/id.js
+++ b/apps/encryption/l10n/id.js
@@ -25,10 +25,13 @@ OC.L10N.register(
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Kunci privat tidak sah untuk Aplikasi Enskripsi. Silakan perbarui sandi kunci privat anda pada pengaturan pribadi untuk memulihkan akses ke berkas anda yang dienskripsi.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Aplikasi Enskripsi telah diaktifkan tetapi kunci tidak diinisialisasi, silakan log-out dan log-in lagi",
"Encryption App is enabled and ready" : "Apl Enkripsi telah diaktifkan dan siap",
+ "one-time password for server-side-encryption" : "Sandi sekali pakai untuk server-side-encryption",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tidak dapat mendekripsi berkas ini, mungkin ini adalah berkas bersama. Silakan meminta pemilik berkas ini untuk membagikan kembali dengan Anda.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tidak dapat membaca berkas ini, kemungkinan merupakan berkas berbagi. Silakan minta pemilik berkas untuk membagikan ulang kepada Anda.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Hai,\n\nadmin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi '%s'.\n\nSilakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar ownCloud' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi-masuk saat ini.\n\n",
"The share will expire on %s." : "Pembagian akan berakhir pada %s.",
"Cheers!" : "Horee!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hai,<br><br>admin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi <strong>%s</strong>.<br><br>Silakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar ownCloud' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi masuk yang baru.<br><br>",
"Enable recovery key" : "Aktifkan kunci pemulihan",
"Disable recovery key" : "Nonaktifkan kunci pemulihan",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kunci pemulihan adalah kunci enkripsi tambahan yang digunakan untuk mengenkripsi berkas. Kunci pemulihan memungkinkan untuk memulihkan berkas-berkas pengguna ketika pengguna tersebut melupakan sandi mereka.",
diff --git a/apps/encryption/l10n/id.json b/apps/encryption/l10n/id.json
index 59f39b2ea3a..3771f7e935f 100644
--- a/apps/encryption/l10n/id.json
+++ b/apps/encryption/l10n/id.json
@@ -23,10 +23,13 @@
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Kunci privat tidak sah untuk Aplikasi Enskripsi. Silakan perbarui sandi kunci privat anda pada pengaturan pribadi untuk memulihkan akses ke berkas anda yang dienskripsi.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Aplikasi Enskripsi telah diaktifkan tetapi kunci tidak diinisialisasi, silakan log-out dan log-in lagi",
"Encryption App is enabled and ready" : "Apl Enkripsi telah diaktifkan dan siap",
+ "one-time password for server-side-encryption" : "Sandi sekali pakai untuk server-side-encryption",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tidak dapat mendekripsi berkas ini, mungkin ini adalah berkas bersama. Silakan meminta pemilik berkas ini untuk membagikan kembali dengan Anda.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Tidak dapat membaca berkas ini, kemungkinan merupakan berkas berbagi. Silakan minta pemilik berkas untuk membagikan ulang kepada Anda.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Hai,\n\nadmin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi '%s'.\n\nSilakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar ownCloud' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi-masuk saat ini.\n\n",
"The share will expire on %s." : "Pembagian akan berakhir pada %s.",
"Cheers!" : "Horee!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hai,<br><br>admin mengaktifkan server-side-encryption. Berkas-berkas Anda dienkripsi menggunakan sandi <strong>%s</strong>.<br><br>Silakan masuk di antarmuka web, pergi ke bagian 'modul enkripsi dasar ownCloud' pada pengaturan pribadi Anda dan perbarui sandi enkripsi Anda dengan memasukkan sandi ini kedalam kolom 'sandi masuk yang lama' dan sandi masuk yang baru.<br><br>",
"Enable recovery key" : "Aktifkan kunci pemulihan",
"Disable recovery key" : "Nonaktifkan kunci pemulihan",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kunci pemulihan adalah kunci enkripsi tambahan yang digunakan untuk mengenkripsi berkas. Kunci pemulihan memungkinkan untuk memulihkan berkas-berkas pengguna ketika pengguna tersebut melupakan sandi mereka.",
diff --git a/apps/encryption/l10n/nl.js b/apps/encryption/l10n/nl.js
index ec7da324218..0655b6d29bd 100644
--- a/apps/encryption/l10n/nl.js
+++ b/apps/encryption/l10n/nl.js
@@ -25,10 +25,13 @@ OC.L10N.register(
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Ongeldige privésleutel voor crypto app. Werk het privésleutel wachtwoord bij in uw persoonlijke instellingen om opnieuw toegang te krijgen tot uw versleutelde bestanden.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Crypto app is geactiveerd, maar uw sleutels werden niet geïnitialiseerd. Log uit en log daarna opnieuw in.",
"Encryption App is enabled and ready" : "Encryptie app is geactiveerd en gereed",
+ "one-time password for server-side-encryption" : "eenmalig wachtwoord voor server-side versleuteling",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Kan dit bestand niet ontcijferen, waarschijnlijk is het een gedeeld bestand, Vraag de eigenaar om het bestand opnieuw met u te delen.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Kan dit bestand niet lezen, waarschijnlijk is het een gedeeld bestand. Vraag de eigenaar om het bestand opnieuw met u te delen.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Hallo daar,\n\nde beheerder heeft server-side versleuteling ingeschakeld. Uw bestanden werden versleuteld met het wachtwoord '%s'.\n\nLogin op de webinterface, ga naar 'ownCloud basis cryptomodule' in uw persoonlijke instellingen en pas uw cryptowachtwoord aan door dit wachtwoord in het 'oude inlog wachtwoord' veld in te vullen alsmede in uw huidige inlogwachtwoord.\n",
"The share will expire on %s." : "De share vervalt op %s.",
"Cheers!" : "Proficiat!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hallo daar,<br><br>de beheerder heeft server-side versleuteling ingeschakeld. Uw bestanden werden versleuteld met het wachtwoord <strong>%s</strong>.<br><br>Login op de webinterface, ga naar 'ownCloud basis cryptomodule' in uw persoonlijke instellingen en pas uw cryptowachtwoord aan door dit wachtwoord in het \"oude inlog wachtwoord\" veld in te vullen alsmede in uw huidige inlogwachtwoord.<br><br>",
"Enable recovery key" : "Activeer herstelsleutel",
"Disable recovery key" : "Deactiveer herstelsleutel",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "De herstelsleutel is een extra cryptografische sleutel die wordt gebruikt om bestanden te versleutelen. Die maakt het mogelijk bestanden te herstellen als de gebruiker zijn of haar wachtwoord vergeet.",
diff --git a/apps/encryption/l10n/nl.json b/apps/encryption/l10n/nl.json
index 40ac3349e14..00f6e67822e 100644
--- a/apps/encryption/l10n/nl.json
+++ b/apps/encryption/l10n/nl.json
@@ -23,10 +23,13 @@
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Ongeldige privésleutel voor crypto app. Werk het privésleutel wachtwoord bij in uw persoonlijke instellingen om opnieuw toegang te krijgen tot uw versleutelde bestanden.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Crypto app is geactiveerd, maar uw sleutels werden niet geïnitialiseerd. Log uit en log daarna opnieuw in.",
"Encryption App is enabled and ready" : "Encryptie app is geactiveerd en gereed",
+ "one-time password for server-side-encryption" : "eenmalig wachtwoord voor server-side versleuteling",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Kan dit bestand niet ontcijferen, waarschijnlijk is het een gedeeld bestand, Vraag de eigenaar om het bestand opnieuw met u te delen.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Kan dit bestand niet lezen, waarschijnlijk is het een gedeeld bestand. Vraag de eigenaar om het bestand opnieuw met u te delen.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Hallo daar,\n\nde beheerder heeft server-side versleuteling ingeschakeld. Uw bestanden werden versleuteld met het wachtwoord '%s'.\n\nLogin op de webinterface, ga naar 'ownCloud basis cryptomodule' in uw persoonlijke instellingen en pas uw cryptowachtwoord aan door dit wachtwoord in het 'oude inlog wachtwoord' veld in te vullen alsmede in uw huidige inlogwachtwoord.\n",
"The share will expire on %s." : "De share vervalt op %s.",
"Cheers!" : "Proficiat!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Hallo daar,<br><br>de beheerder heeft server-side versleuteling ingeschakeld. Uw bestanden werden versleuteld met het wachtwoord <strong>%s</strong>.<br><br>Login op de webinterface, ga naar 'ownCloud basis cryptomodule' in uw persoonlijke instellingen en pas uw cryptowachtwoord aan door dit wachtwoord in het \"oude inlog wachtwoord\" veld in te vullen alsmede in uw huidige inlogwachtwoord.<br><br>",
"Enable recovery key" : "Activeer herstelsleutel",
"Disable recovery key" : "Deactiveer herstelsleutel",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "De herstelsleutel is een extra cryptografische sleutel die wordt gebruikt om bestanden te versleutelen. Die maakt het mogelijk bestanden te herstellen als de gebruiker zijn of haar wachtwoord vergeet.",
diff --git a/apps/encryption/l10n/tr.js b/apps/encryption/l10n/tr.js
index 2c8eff7e62b..96db8f91209 100644
--- a/apps/encryption/l10n/tr.js
+++ b/apps/encryption/l10n/tr.js
@@ -25,10 +25,13 @@ OC.L10N.register(
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Şifreleme Uygulaması için geçersiz özel anahtar. Lütfen şifreli dosyalarınıza erişimi tekrar kazanabilmek için kişisel ayarlarınızdan özel anahtar parolanızı güncelleyin.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Şifreleme Uygulaması etkin ancak anahtarlarınız başlatılmamış. Lütfen oturumu kapatıp yeniden açın",
"Encryption App is enabled and ready" : "Şifreleme Uygulaması etkin ve hazır",
+ "one-time password for server-side-encryption" : "sunucu tarafında şifleme için tek kullanımlık parola",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosya muhtemelen bir paylaşılan dosya olduğundan şifrelemesi kaldırılamıyor. Lütfen dosyayı sizinle bir daha paylaşması için dosya sahibi ile iletişime geçin.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosya muhtemelen bir paylaşılan dosya olduğundan okunamıyor. Lütfen dosyayı sizinle bir daha paylaşması için dosya sahibi ile iletişime geçin.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Selam,\n\nsistem yöneticisi sunucu tarafında şifrelemeyi etkinleştirdi. Dosyalarınız '%s' parolası kullanılarak şifrelendi.\n\nLütfen web arayüzünde oturum açın ve kişisel ayarlarınızdan 'ownCloud temel şifreleme modülü'ne giderek 'eski oturum parolası' alanına bu parolayı girerek şifreleme parolanızı ve mevcut oturum açma parolanızı güncelleyin.\n\n",
"The share will expire on %s." : "Bu paylaşım %s tarihinde sona erecek.",
"Cheers!" : "Hoşçakalın!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Selam,<br><br>sistem yöneticisi sunucu tarafında şifrelemeyi etkinleştirdi. Dosyalarınız <strong>%s</strong> parolası kullanılarak şifrelendi.<br><br>Lütfen web arayüzünde oturum açın ve kişisel ayarlarınızdan 'ownCloud temel şifreleme modülü'ne giderek 'eski oturum parolası' alanına bu parolayı girerek şifreleme parolanızı ve mevcut oturum açma parolanızı güncelleyin.<br><br>",
"Enable recovery key" : "Kurtarma anahtarını etkinleştir",
"Disable recovery key" : "Kurtarma anahtarını devre dışı bırak",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kurtarma anahtarı, dosyaların şifrelenmesi için daha fazla \nşifreleme sunar. Bu kullanıcının dosyasının şifresini unuttuğunda kurtarmasına imkan verir.",
diff --git a/apps/encryption/l10n/tr.json b/apps/encryption/l10n/tr.json
index a1bb9b6a5d9..be6f6a5dfdd 100644
--- a/apps/encryption/l10n/tr.json
+++ b/apps/encryption/l10n/tr.json
@@ -23,10 +23,13 @@
"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." : "Şifreleme Uygulaması için geçersiz özel anahtar. Lütfen şifreli dosyalarınıza erişimi tekrar kazanabilmek için kişisel ayarlarınızdan özel anahtar parolanızı güncelleyin.",
"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" : "Şifreleme Uygulaması etkin ancak anahtarlarınız başlatılmamış. Lütfen oturumu kapatıp yeniden açın",
"Encryption App is enabled and ready" : "Şifreleme Uygulaması etkin ve hazır",
+ "one-time password for server-side-encryption" : "sunucu tarafında şifleme için tek kullanımlık parola",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosya muhtemelen bir paylaşılan dosya olduğundan şifrelemesi kaldırılamıyor. Lütfen dosyayı sizinle bir daha paylaşması için dosya sahibi ile iletişime geçin.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Bu dosya muhtemelen bir paylaşılan dosya olduğundan okunamıyor. Lütfen dosyayı sizinle bir daha paylaşması için dosya sahibi ile iletişime geçin.",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Selam,\n\nsistem yöneticisi sunucu tarafında şifrelemeyi etkinleştirdi. Dosyalarınız '%s' parolası kullanılarak şifrelendi.\n\nLütfen web arayüzünde oturum açın ve kişisel ayarlarınızdan 'ownCloud temel şifreleme modülü'ne giderek 'eski oturum parolası' alanına bu parolayı girerek şifreleme parolanızı ve mevcut oturum açma parolanızı güncelleyin.\n\n",
"The share will expire on %s." : "Bu paylaşım %s tarihinde sona erecek.",
"Cheers!" : "Hoşçakalın!",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Selam,<br><br>sistem yöneticisi sunucu tarafında şifrelemeyi etkinleştirdi. Dosyalarınız <strong>%s</strong> parolası kullanılarak şifrelendi.<br><br>Lütfen web arayüzünde oturum açın ve kişisel ayarlarınızdan 'ownCloud temel şifreleme modülü'ne giderek 'eski oturum parolası' alanına bu parolayı girerek şifreleme parolanızı ve mevcut oturum açma parolanızı güncelleyin.<br><br>",
"Enable recovery key" : "Kurtarma anahtarını etkinleştir",
"Disable recovery key" : "Kurtarma anahtarını devre dışı bırak",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "Kurtarma anahtarı, dosyaların şifrelenmesi için daha fazla \nşifreleme sunar. Bu kullanıcının dosyasının şifresini unuttuğunda kurtarmasına imkan verir.",
diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php
index 6c4c108f50a..5d1bb92460a 100644
--- a/apps/encryption/lib/crypto/crypt.php
+++ b/apps/encryption/lib/crypto/crypt.php
@@ -398,7 +398,7 @@ class Crypt {
}
}
- return true;
+ return false;
}
/**
diff --git a/apps/encryption/tests/controller/SettingsControllerTest.php b/apps/encryption/tests/controller/SettingsControllerTest.php
index d985c7d7d25..34aa5a27a75 100644
--- a/apps/encryption/tests/controller/SettingsControllerTest.php
+++ b/apps/encryption/tests/controller/SettingsControllerTest.php
@@ -54,6 +54,9 @@ class SettingsControllerTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
private $sessionMock;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ private $ocSessionMock;
+
protected function setUp() {
parent::setUp();
@@ -91,9 +94,11 @@ class SettingsControllerTest extends TestCase {
])
->getMock();
+ $this->ocSessionMock = $this->getMockBuilder('\OCP\ISession')->disableOriginalConstructor()->getMock();
+
$this->userSessionMock->expects($this->any())
->method('getUID')
- ->willReturn('testUser');
+ ->willReturn('testUserUid');
$this->userSessionMock->expects($this->any())
->method($this->anything())
@@ -110,7 +115,8 @@ class SettingsControllerTest extends TestCase {
$this->userSessionMock,
$this->keyManagerMock,
$this->cryptMock,
- $this->sessionMock
+ $this->sessionMock,
+ $this->ocSessionMock
);
}
@@ -122,8 +128,10 @@ class SettingsControllerTest extends TestCase {
$oldPassword = 'old';
$newPassword = 'new';
+ $this->userSessionMock->expects($this->once())->method('getUID')->willReturn('uid');
+
$this->userManagerMock
- ->expects($this->once())
+ ->expects($this->exactly(2))
->method('checkPassword')
->willReturn(false);
@@ -171,16 +179,22 @@ class SettingsControllerTest extends TestCase {
$oldPassword = 'old';
$newPassword = 'new';
- $this->userSessionMock
- ->expects($this->once())
- ->method('getUID')
- ->willReturn('testUser');
+ $this->ocSessionMock->expects($this->once())
+ ->method('get')->with('loginname')->willReturn('testUser');
$this->userManagerMock
- ->expects($this->once())
+ ->expects($this->at(0))
+ ->method('checkPassword')
+ ->with('testUserUid', 'new')
+ ->willReturn(false);
+ $this->userManagerMock
+ ->expects($this->at(1))
->method('checkPassword')
+ ->with('testUser', 'new')
->willReturn(true);
+
+
$this->cryptMock
->expects($this->once())
->method('decryptPrivateKey')
@@ -200,7 +214,7 @@ class SettingsControllerTest extends TestCase {
$this->keyManagerMock
->expects($this->once())
->method('setPrivateKey')
- ->with($this->equalTo('testUser'), $this->equalTo('header.encryptedKey'));
+ ->with($this->equalTo('testUserUid'), $this->equalTo('header.encryptedKey'));
$this->sessionMock
->expects($this->once())
diff --git a/apps/encryption/tests/lib/crypto/cryptTest.php b/apps/encryption/tests/lib/crypto/cryptTest.php
index 3c7767a8908..c6f16e952d7 100644
--- a/apps/encryption/tests/lib/crypto/cryptTest.php
+++ b/apps/encryption/tests/lib/crypto/cryptTest.php
@@ -363,4 +363,19 @@ class cryptTest extends TestCase {
];
}
+ public function testIsValidPrivateKey() {
+ $res = openssl_pkey_new();
+ openssl_pkey_export($res, $privateKey);
+
+ // valid private key
+ $this->assertTrue(
+ $this->invokePrivate($this->crypt, 'isValidPrivateKey', [$privateKey])
+ );
+
+ // invalid private key
+ $this->assertFalse(
+ $this->invokePrivate($this->crypt, 'isValidPrivateKey', ['foo'])
+ );
+ }
+
}
diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
index dafd8c24573..8eded7acda1 100644
--- a/apps/files/css/detailsView.css
+++ b/apps/files/css/detailsView.css
@@ -9,11 +9,41 @@
#app-sidebar .mainFileInfoView {
margin-right: 20px; /* accomodate for close icon */
+ float:left;
+ display:block;
+ width: 100%;
+}
+
+#app-sidebar .file-details-container {
+ display: inline-block;
+ float: left;
+}
+
+#app-sidebar .thumbnailContainer.image {
+ margin-left: -15px;
+ margin-right: -35px; /* 15 + 20 for the close button */
+ margin-top: -15px;
+}
+
+#app-sidebar .image .thumbnail {
+ width:100%;
+ display:block;
+ height: 250px;
+ background-repeat: no-repeat;
+ background-position: 50% top;
+ background-size: 100%;
+ float: none;
+ margin: 0;
+}
+
+#app-sidebar .image.portrait .thumbnail {
+ background-size: contain;
}
#app-sidebar .thumbnail {
width: 75px;
height: 75px;
+ display: inline-block;
float: left;
margin-right: 10px;
background-size: 75px;
@@ -31,10 +61,16 @@
padding-bottom: 3px;
}
+#app-sidebar .fileName h3 {
+ max-width: 300px;
+ float:left;
+}
+
#app-sidebar .file-details {
margin-top: 3px;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
opacity: .5;
+ float:left;
}
#app-sidebar .action-favorite {
vertical-align: text-bottom;
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index a9c85127c66..375666141ba 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -137,6 +137,7 @@
bottom: 44px;
width: inherit !important;
background-color: #fff;
+ border-right: 1px solid #eee;
}
/* double padding to account for Deleted files entry, issue with Firefox */
.app-files #app-navigation > ul li:nth-last-child(2) {
diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js
index a4ebe90cd64..83d7fd4a178 100644
--- a/apps/files/js/detailsview.js
+++ b/apps/files/js/detailsview.js
@@ -10,24 +10,20 @@
(function() {
var TEMPLATE =
- '<div>' +
' <div class="detailFileInfoContainer">' +
' </div>' +
- ' <div>' +
- ' {{#if tabHeaders}}' +
- ' <ul class="tabHeaders">' +
+ ' {{#if tabHeaders}}' +
+ ' <ul class="tabHeaders">' +
' {{#each tabHeaders}}' +
' <li class="tabHeader" data-tabid="{{tabId}}" data-tabindex="{{tabIndex}}">' +
' <a href="#">{{label}}</a>' +
' </li>' +
' {{/each}}' +
- ' </ul>' +
- ' {{/if}}' +
- ' <div class="tabsContainer">' +
- ' </div>' +
+ ' </ul>' +
+ ' {{/if}}' +
+ ' <div class="tabsContainer">' +
' </div>' +
- ' <a class="close icon-close" href="#" alt="{{closeLabel}}"></a>' +
- '</div>';
+ ' <a class="close icon-close" href="#" alt="{{closeLabel}}"></a>';
/**
* @class OCA.Files.DetailsView
@@ -268,4 +264,3 @@
OCA.Files.DetailsView = DetailsView;
})();
-
diff --git a/apps/files/js/fileinfomodel.js b/apps/files/js/fileinfomodel.js
index 05060854fba..1c850239cdc 100644
--- a/apps/files/js/fileinfomodel.js
+++ b/apps/files/js/fileinfomodel.js
@@ -53,6 +53,15 @@
},
/**
+ * Returns whether this file is an image
+ *
+ * @return {boolean} true if this is an image, false otherwise
+ */
+ isImage: function() {
+ return this.get('mimetype').substr(0, 6) === 'image/';
+ },
+
+ /**
* Returns the full path to this file
*
* @return {string} full path
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index ac96d587015..9593ee79e66 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -1359,6 +1359,12 @@
if (options.y) {
urlSpec.y = options.y;
}
+ if (options.a) {
+ urlSpec.a = options.a;
+ }
+ if (options.mode) {
+ urlSpec.mode = options.mode;
+ }
if (etag){
// use etag as cache buster
@@ -1377,9 +1383,14 @@
img.onload = function(){
// if loading the preview image failed (no preview for the mimetype) then img.width will < 5
if (img.width > 5) {
- ready(previewURL);
+ ready(previewURL, img);
+ } else if (options.error) {
+ options.error();
}
};
+ if (options.error) {
+ img.onerror = options.error;
+ }
img.src = previewURL;
},
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
index 513f833299a..785eed8d712 100644
--- a/apps/files/js/mainfileinfodetailview.js
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -10,14 +10,17 @@
(function() {
var TEMPLATE =
- '<a href="#" class="thumbnail action-default"></a><div title="{{name}}" class="fileName ellipsis">{{name}}</div>' +
- '<div class="file-details ellipsis">' +
- ' <a href="#" ' +
- ' alt="{{starAltText}}"' +
- ' class="action action-favorite favorite">' +
- ' <img class="svg" src="{{starIcon}}" />' +
- ' </a>' +
- ' {{#if hasSize}}<span class="size" title="{{altSize}}">{{size}}</span>, {{/if}}<span class="date" title="{{altDate}}">{{date}}</span>' +
+ '<div class="thumbnailContainer"><a href="#" class="thumbnail action-default"></a></div>' +
+ '<div class="file-details-container">' +
+ '<div class="fileName"><h3 title="{{name}}" class="ellipsis">{{name}}</h3></div>' +
+ ' <div class="file-details ellipsis">' +
+ ' <a href="#" ' +
+ ' alt="{{starAltText}}"' +
+ ' class="action action-favorite favorite">' +
+ ' <img class="svg" src="{{starIcon}}" />' +
+ ' </a>' +
+ ' {{#if hasSize}}<span class="size" title="{{altSize}}">{{size}}</span>, {{/if}}<span class="date" title="{{altDate}}">{{date}}</span>' +
+ ' </div>' +
'</div>';
/**
@@ -103,6 +106,7 @@
if (this.model) {
var isFavorite = (this.model.get('tags') || []).indexOf(OC.TAG_FAVORITE) >= 0;
this.$el.html(this.template({
+ type: this.model.isImage()? 'image': '',
nameLabel: t('files', 'Name'),
name: this.model.get('displayName') || this.model.get('name'),
pathLabel: t('files', 'Path'),
@@ -120,16 +124,51 @@
// TODO: we really need OC.Previews
var $iconDiv = this.$el.find('.thumbnail');
+ $iconDiv.addClass('icon-loading');
+ $container = this.$el.find('.thumbnailContainer');
if (!this.model.isDirectory()) {
this._fileList.lazyLoadPreview({
path: this.model.getFullPath(),
mime: this.model.get('mimetype'),
etag: this.model.get('etag'),
- x: 75,
- y: 75,
- callback: function(previewUrl) {
- $iconDiv.css('background-image', 'url("' + previewUrl + '")');
- }
+ y: this.model.isImage() ? 250: 75,
+ x: this.model.isImage() ? 99999 /* only limit on y */ : 75,
+ a: this.model.isImage() ? 1 : null,
+ callback: function(previewUrl, img) {
+ $iconDiv.previewImg = previewUrl;
+ if (img) {
+ $iconDiv.removeClass('icon-loading');
+ if(img.height > img.width) {
+ $container.addClass('portrait');
+ }
+ }
+ if (this.model.isImage() && img) {
+ $iconDiv.parent().addClass('image');
+ var targetHeight = img.height / window.devicePixelRatio;
+ if (targetHeight <= 75) {
+ $container.removeClass('image'); // small enough to fit in normaly
+ targetHeight = 75;
+ }
+ } else {
+ targetHeight = 75;
+ }
+
+ // only set background when we have an actual preview
+ // when we dont have a preview we show the mime icon in the error handler
+ if (img) {
+ $iconDiv.css({
+ 'background-image': 'url("' + previewUrl + '")',
+ 'height': targetHeight
+ });
+ }
+ }.bind(this),
+ error: function() {
+ $iconDiv.removeClass('icon-loading');
+ this.$el.find('.thumbnailContainer').removeClass('image'); //fall back to regular view
+ $iconDiv.css({
+ 'background-image': 'url("' + $iconDiv.previewImg + '")'
+ });
+ }.bind(this)
});
} else {
// TODO: special icons / shared / external
diff --git a/apps/files/l10n/tr.js b/apps/files/l10n/tr.js
index 345b9ffd9fb..2145fb5c9fc 100644
--- a/apps/files/l10n/tr.js
+++ b/apps/files/l10n/tr.js
@@ -67,6 +67,8 @@ OC.L10N.register(
"Storage of {owner} is almost full ({usedSpacePercent}%)" : " {owner} depolama alanı neredeyse dolu ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "Depolama alanınız neredeyse dolu (%{usedSpacePercent})",
"_matches '{filter}'_::_match '{filter}'_" : ["'{filter}' ile eşleşiyor","'{filter}' ile eşleşiyor"],
+ "Path" : "Yol",
+ "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"],
"Favorited" : "Sık kullanılanlara eklendi",
"Favorite" : "Sık kullanılan",
"An error occurred while trying to update the tags" : "Etiketler güncellenmeye çalışılırken bir hata oluştu",
@@ -90,6 +92,7 @@ OC.L10N.register(
"File handling" : "Dosya işlemleri",
"Maximum upload size" : "Azami yükleme boyutu",
"max. possible: " : "mümkün olan en fazla: ",
+ "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM ile bu değerin kaydedildikten sonra etkili olabilmesi için 5 dakika gerekebilir.",
"Save" : "Kaydet",
"Can not be edited from here due to insufficient permissions." : "Yetersiz izinler buradan düzenlenemez.",
"Settings" : "Ayarlar",
diff --git a/apps/files/l10n/tr.json b/apps/files/l10n/tr.json
index fc4ca146881..5a1e5f9ec7a 100644
--- a/apps/files/l10n/tr.json
+++ b/apps/files/l10n/tr.json
@@ -65,6 +65,8 @@
"Storage of {owner} is almost full ({usedSpacePercent}%)" : " {owner} depolama alanı neredeyse dolu ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "Depolama alanınız neredeyse dolu (%{usedSpacePercent})",
"_matches '{filter}'_::_match '{filter}'_" : ["'{filter}' ile eşleşiyor","'{filter}' ile eşleşiyor"],
+ "Path" : "Yol",
+ "_%n byte_::_%n bytes_" : ["%n bayt","%n bayt"],
"Favorited" : "Sık kullanılanlara eklendi",
"Favorite" : "Sık kullanılan",
"An error occurred while trying to update the tags" : "Etiketler güncellenmeye çalışılırken bir hata oluştu",
@@ -88,6 +90,7 @@
"File handling" : "Dosya işlemleri",
"Maximum upload size" : "Azami yükleme boyutu",
"max. possible: " : "mümkün olan en fazla: ",
+ "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "PHP-FPM ile bu değerin kaydedildikten sonra etkili olabilmesi için 5 dakika gerekebilir.",
"Save" : "Kaydet",
"Can not be edited from here due to insufficient permissions." : "Yetersiz izinler buradan düzenlenemez.",
"Settings" : "Ayarlar",
diff --git a/apps/files/l10n/zh_CN.js b/apps/files/l10n/zh_CN.js
index 92945f43ba5..9633e2961a9 100644
--- a/apps/files/l10n/zh_CN.js
+++ b/apps/files/l10n/zh_CN.js
@@ -67,6 +67,8 @@ OC.L10N.register(
"Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} 的存储空间即将用完 ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "您的存储空间即将用完 ({usedSpacePercent}%)",
"_matches '{filter}'_::_match '{filter}'_" : ["匹配“{filter}”"],
+ "Path" : "路径",
+ "_%n byte_::_%n bytes_" : ["%n 字节"],
"Favorited" : "已收藏",
"Favorite" : "收藏",
"An error occurred while trying to update the tags" : "更新标签时出错",
@@ -90,6 +92,7 @@ OC.L10N.register(
"File handling" : "文件处理",
"Maximum upload size" : "最大上传大小",
"max. possible: " : "最大允许: ",
+ "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "对于 PHP-FPM 这个值保存后可能需要长达5分钟才会生效。",
"Save" : "保存",
"Can not be edited from here due to insufficient permissions." : "由于权限不足无法在此编辑。",
"Settings" : "设置",
diff --git a/apps/files/l10n/zh_CN.json b/apps/files/l10n/zh_CN.json
index 5bd652a3444..b803908729f 100644
--- a/apps/files/l10n/zh_CN.json
+++ b/apps/files/l10n/zh_CN.json
@@ -65,6 +65,8 @@
"Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} 的存储空间即将用完 ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "您的存储空间即将用完 ({usedSpacePercent}%)",
"_matches '{filter}'_::_match '{filter}'_" : ["匹配“{filter}”"],
+ "Path" : "路径",
+ "_%n byte_::_%n bytes_" : ["%n 字节"],
"Favorited" : "已收藏",
"Favorite" : "收藏",
"An error occurred while trying to update the tags" : "更新标签时出错",
@@ -88,6 +90,7 @@
"File handling" : "文件处理",
"Maximum upload size" : "最大上传大小",
"max. possible: " : "最大允许: ",
+ "With PHP-FPM this value may take up to 5 minutes to take effect after saving." : "对于 PHP-FPM 这个值保存后可能需要长达5分钟才会生效。",
"Save" : "保存",
"Can not be edited from here due to insufficient permissions." : "由于权限不足无法在此编辑。",
"Settings" : "设置",
diff --git a/apps/files/l10n/zh_TW.js b/apps/files/l10n/zh_TW.js
index 049b63814a6..eeefcd95884 100644
--- a/apps/files/l10n/zh_TW.js
+++ b/apps/files/l10n/zh_TW.js
@@ -65,7 +65,11 @@ OC.L10N.register(
"Your storage is full, files can not be updated or synced anymore!" : "您的儲存空間已滿,沒有辦法再更新或是同步檔案!",
"Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} 的儲存空間快要滿了 ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "您的儲存空間快要滿了 ({usedSpacePercent}%)",
+ "Path" : "路徑",
+ "_%n byte_::_%n bytes_" : ["%n 位元組"],
+ "Favorited" : "已加入最愛",
"Favorite" : "我的最愛",
+ "An error occurred while trying to update the tags" : "更新標籤時發生錯誤",
"A new file or folder has been <strong>created</strong>" : "新的檔案或目錄已被 <strong>建立</strong>",
"A file or folder has been <strong>changed</strong>" : "檔案或目錄已被 <strong>變更</strong>",
"A file or folder has been <strong>deleted</strong>" : "檔案或目錄已被 <strong>刪除</strong>",
diff --git a/apps/files/l10n/zh_TW.json b/apps/files/l10n/zh_TW.json
index 7b047c3c012..84af9fae39e 100644
--- a/apps/files/l10n/zh_TW.json
+++ b/apps/files/l10n/zh_TW.json
@@ -63,7 +63,11 @@
"Your storage is full, files can not be updated or synced anymore!" : "您的儲存空間已滿,沒有辦法再更新或是同步檔案!",
"Storage of {owner} is almost full ({usedSpacePercent}%)" : "{owner} 的儲存空間快要滿了 ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "您的儲存空間快要滿了 ({usedSpacePercent}%)",
+ "Path" : "路徑",
+ "_%n byte_::_%n bytes_" : ["%n 位元組"],
+ "Favorited" : "已加入最愛",
"Favorite" : "我的最愛",
+ "An error occurred while trying to update the tags" : "更新標籤時發生錯誤",
"A new file or folder has been <strong>created</strong>" : "新的檔案或目錄已被 <strong>建立</strong>",
"A file or folder has been <strong>changed</strong>" : "檔案或目錄已被 <strong>變更</strong>",
"A file or folder has been <strong>deleted</strong>" : "檔案或目錄已被 <strong>刪除</strong>",
diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js
index 582824585b5..3d78312c86e 100644
--- a/apps/files/tests/js/mainfileinfodetailviewSpec.js
+++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js
@@ -55,8 +55,8 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
var clock = sinon.useFakeTimers(Date.UTC(2015, 6, 17, 1, 2, 0, 3));
var dateExpected = OC.Util.formatDate(Date(Date.UTC(2015, 6, 17, 1, 2, 0, 0)));
view.setFileInfo(testFileInfo);
- expect(view.$el.find('.fileName').text()).toEqual('One.txt');
- expect(view.$el.find('.fileName').attr('title')).toEqual('One.txt');
+ expect(view.$el.find('.fileName h3').text()).toEqual('One.txt');
+ expect(view.$el.find('.fileName h3').attr('title')).toEqual('One.txt');
expect(view.$el.find('.size').text()).toEqual('117.7 MB');
expect(view.$el.find('.size').attr('title')).toEqual('123456789 bytes');
expect(view.$el.find('.date').text()).toEqual('a few seconds ago');
@@ -110,8 +110,8 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
testFileInfo.set('displayName', 'hello.txt');
view.setFileInfo(testFileInfo);
- expect(view.$el.find('.fileName').text()).toEqual('hello.txt');
- expect(view.$el.find('.fileName').attr('title')).toEqual('hello.txt');
+ expect(view.$el.find('.fileName h3').text()).toEqual('hello.txt');
+ expect(view.$el.find('.fileName h3').attr('title')).toEqual('hello.txt');
});
it('rerenders when changes are made on the model', function() {
view.setFileInfo(testFileInfo);
diff --git a/apps/files_external/l10n/id.js b/apps/files_external/l10n/id.js
index a15106a8f74..e26ad12f3a8 100644
--- a/apps/files_external/l10n/id.js
+++ b/apps/files_external/l10n/id.js
@@ -1,6 +1,9 @@
OC.L10N.register(
"files_external",
{
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "Permintaan pengambilan token gagal. Pastikan kunci dan kerahasiaan aplikasi Anda sudah benar.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "Akses pengambilan token gagal. Pastikan kunci dan kerahasiaan aplikasi Anda sudah benar.",
+ "Please provide a valid app key and secret." : "Silakan berikan kunci dan kerahasiaan aplikasi yang benar.",
"Step 1 failed. Exception: %s" : "Langkah 1 gagal. Kecuali: %s",
"Step 2 failed. Exception: %s" : "Langkah 2 gagal. Kecuali: %s",
"External storage" : "Penyimpanan eksternal",
@@ -22,12 +25,19 @@ OC.L10N.register(
"SFTP with secret key login" : "SFTP dengan kunci rahasia masuk",
"Public key" : "Kunci Public",
"Storage with id \"%i\" not found" : "Penyimpanan dengan id \"%i\" tidak ditemukan",
+ "Invalid backend or authentication mechanism class" : "Beckend atau kelas mekanisme otentikasi salah.",
"Invalid mount point" : "Mount point salah",
+ "Objectstore forbidden" : "Objectstore terlarang",
"Invalid storage backend \"%s\"" : "Backend penyimpanan \"%s\" salah",
+ "Unsatisfied backend parameters" : "Parameter backend tidak lengkap",
+ "Unsatisfied authentication mechanism parameters" : "Parameter mekanisme otentikasi tidak lengkap",
+ "Admin-only storage backend \"%s\"" : "Backend penyimpanan hanya-admin \"%s\"",
"Personal" : "Pribadi",
"System" : "Sistem",
"Grant access" : "Berikan hak akses",
"Access granted" : "Akses diberikan",
+ "Error configuring OAuth1" : "Kesalahan mengkonfigurasi OAuth1",
+ "Error configuring OAuth2" : "Kesalahan mengkonfigurasi OAuth2",
"Enable encryption" : "Aktifkan enkripsi",
"Enable previews" : "Aktifkan pratinjau",
"Check for changes" : "Periksa perubahan",
@@ -39,12 +49,19 @@ OC.L10N.register(
"Saved" : "Disimpan",
"Generate keys" : "Hasilkan kunci",
"Error generating key pair" : "Kesalahan saat menghasilkan pasangan kunci",
+ "Access key" : "Kunci akses",
+ "Secret key" : "Kunci rahasia",
+ "Builtin" : "Internal",
"None" : "Tidak ada",
+ "OAuth1" : "OAuth1",
"App key" : "Kunci Apl",
"App secret" : "Rahasia Apl",
+ "OAuth2" : "OAuth2",
"Client ID" : "ID Klien",
"Client secret" : "Rahasia klien",
+ "Username and password" : "Nama pengguna dan sandi",
"Password" : "Sandi",
+ "Session credentials" : "Kredensial sesi",
"Amazon S3" : "Amazon S3",
"Hostname" : "Nama Host",
"Port" : "Port",
@@ -55,11 +72,15 @@ OC.L10N.register(
"URL" : "URL",
"Secure https://" : "Secure https://",
"Dropbox" : "Dropbox",
+ "FTP" : "FTP",
"Secure ftps://" : "Secure ftps://",
+ "Google Drive" : "Google Drive",
"Local" : "Lokal",
"Location" : "lokasi",
"ownCloud" : "ownCloud",
+ "SFTP" : "SFTP",
"Root" : "Root",
+ "SMB / CIFS" : "SMB / CIFS",
"<b>Note:</b> " : "<b>Catatan:</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>Catatan:</b> Dukungan cURL di PHP tidak diaktifkan atau belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan minta administrator sistem Anda untuk menginstalnya.",
"<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>Catatan:</b> Dukungan FTP di PHP tidak diaktifkan atau belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan minta administrator sistem Anda untuk menginstalnya.",
@@ -71,6 +92,7 @@ OC.L10N.register(
"Scope" : "Skop",
"External Storage" : "Penyimpanan Eksternal",
"Folder name" : "Nama folder",
+ "Authentication" : "Otentikasi",
"Configuration" : "Konfigurasi",
"Available for" : "Tersedia untuk",
"Advanced settings" : "Pengaturan Lanjutan",
diff --git a/apps/files_external/l10n/id.json b/apps/files_external/l10n/id.json
index aa4990ec828..9c83475f756 100644
--- a/apps/files_external/l10n/id.json
+++ b/apps/files_external/l10n/id.json
@@ -1,4 +1,7 @@
{ "translations": {
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "Permintaan pengambilan token gagal. Pastikan kunci dan kerahasiaan aplikasi Anda sudah benar.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "Akses pengambilan token gagal. Pastikan kunci dan kerahasiaan aplikasi Anda sudah benar.",
+ "Please provide a valid app key and secret." : "Silakan berikan kunci dan kerahasiaan aplikasi yang benar.",
"Step 1 failed. Exception: %s" : "Langkah 1 gagal. Kecuali: %s",
"Step 2 failed. Exception: %s" : "Langkah 2 gagal. Kecuali: %s",
"External storage" : "Penyimpanan eksternal",
@@ -20,12 +23,19 @@
"SFTP with secret key login" : "SFTP dengan kunci rahasia masuk",
"Public key" : "Kunci Public",
"Storage with id \"%i\" not found" : "Penyimpanan dengan id \"%i\" tidak ditemukan",
+ "Invalid backend or authentication mechanism class" : "Beckend atau kelas mekanisme otentikasi salah.",
"Invalid mount point" : "Mount point salah",
+ "Objectstore forbidden" : "Objectstore terlarang",
"Invalid storage backend \"%s\"" : "Backend penyimpanan \"%s\" salah",
+ "Unsatisfied backend parameters" : "Parameter backend tidak lengkap",
+ "Unsatisfied authentication mechanism parameters" : "Parameter mekanisme otentikasi tidak lengkap",
+ "Admin-only storage backend \"%s\"" : "Backend penyimpanan hanya-admin \"%s\"",
"Personal" : "Pribadi",
"System" : "Sistem",
"Grant access" : "Berikan hak akses",
"Access granted" : "Akses diberikan",
+ "Error configuring OAuth1" : "Kesalahan mengkonfigurasi OAuth1",
+ "Error configuring OAuth2" : "Kesalahan mengkonfigurasi OAuth2",
"Enable encryption" : "Aktifkan enkripsi",
"Enable previews" : "Aktifkan pratinjau",
"Check for changes" : "Periksa perubahan",
@@ -37,12 +47,19 @@
"Saved" : "Disimpan",
"Generate keys" : "Hasilkan kunci",
"Error generating key pair" : "Kesalahan saat menghasilkan pasangan kunci",
+ "Access key" : "Kunci akses",
+ "Secret key" : "Kunci rahasia",
+ "Builtin" : "Internal",
"None" : "Tidak ada",
+ "OAuth1" : "OAuth1",
"App key" : "Kunci Apl",
"App secret" : "Rahasia Apl",
+ "OAuth2" : "OAuth2",
"Client ID" : "ID Klien",
"Client secret" : "Rahasia klien",
+ "Username and password" : "Nama pengguna dan sandi",
"Password" : "Sandi",
+ "Session credentials" : "Kredensial sesi",
"Amazon S3" : "Amazon S3",
"Hostname" : "Nama Host",
"Port" : "Port",
@@ -53,11 +70,15 @@
"URL" : "URL",
"Secure https://" : "Secure https://",
"Dropbox" : "Dropbox",
+ "FTP" : "FTP",
"Secure ftps://" : "Secure ftps://",
+ "Google Drive" : "Google Drive",
"Local" : "Lokal",
"Location" : "lokasi",
"ownCloud" : "ownCloud",
+ "SFTP" : "SFTP",
"Root" : "Root",
+ "SMB / CIFS" : "SMB / CIFS",
"<b>Note:</b> " : "<b>Catatan:</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>Catatan:</b> Dukungan cURL di PHP tidak diaktifkan atau belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan minta administrator sistem Anda untuk menginstalnya.",
"<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>Catatan:</b> Dukungan FTP di PHP tidak diaktifkan atau belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan minta administrator sistem Anda untuk menginstalnya.",
@@ -69,6 +90,7 @@
"Scope" : "Skop",
"External Storage" : "Penyimpanan Eksternal",
"Folder name" : "Nama folder",
+ "Authentication" : "Otentikasi",
"Configuration" : "Konfigurasi",
"Available for" : "Tersedia untuk",
"Advanced settings" : "Pengaturan Lanjutan",
diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js
index deeb824f57f..6e3596e197d 100644
--- a/apps/files_external/l10n/it.js
+++ b/apps/files_external/l10n/it.js
@@ -31,6 +31,7 @@ OC.L10N.register(
"Invalid storage backend \"%s\"" : "Motore di archiviazione \"%s\" non valido",
"Unsatisfied backend parameters" : "Parametri del motore non soddisfatti",
"Unsatisfied authentication mechanism parameters" : "Parametri del meccanismo di autenticazione non soddisfatti",
+ "Admin-only storage backend \"%s\"" : "Motore di archiviazione per soli amministratori \"%s\"",
"Personal" : "Personale",
"System" : "Sistema",
"Grant access" : "Concedi l'accesso",
diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json
index f1282447100..1c64b7dbadd 100644
--- a/apps/files_external/l10n/it.json
+++ b/apps/files_external/l10n/it.json
@@ -29,6 +29,7 @@
"Invalid storage backend \"%s\"" : "Motore di archiviazione \"%s\" non valido",
"Unsatisfied backend parameters" : "Parametri del motore non soddisfatti",
"Unsatisfied authentication mechanism parameters" : "Parametri del meccanismo di autenticazione non soddisfatti",
+ "Admin-only storage backend \"%s\"" : "Motore di archiviazione per soli amministratori \"%s\"",
"Personal" : "Personale",
"System" : "Sistema",
"Grant access" : "Concedi l'accesso",
diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js
index a9a66934753..d43bb0f9794 100644
--- a/apps/files_external/l10n/nl.js
+++ b/apps/files_external/l10n/nl.js
@@ -1,6 +1,9 @@
OC.L10N.register(
"files_external",
{
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "Ophalen aanvraag tokens mislukt. Verifieer dat uw app sleutel en geheime sleutel juist zijn.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "Ophalen toegangstokens mislukt. Verifieer dat uw app sleutel en geheime sleutel juist zijn.",
+ "Please provide a valid app key and secret." : "Geef een geldige app sleutel en geheime sleutel op.",
"Step 1 failed. Exception: %s" : "Stap 1 is mislukt. Uitzondering: %s",
"Step 2 failed. Exception: %s" : "Stap 2 is mislukt. Uitzondering: %s",
"External storage" : "Externe opslag",
@@ -22,8 +25,13 @@ OC.L10N.register(
"SFTP with secret key login" : "SFTP met geheime sleutel inlog",
"Public key" : "Publieke sleutel",
"Storage with id \"%i\" not found" : "Opslag met id \"%i\" niet gevonden",
+ "Invalid backend or authentication mechanism class" : "Ongeldige backend of authenticatie mechanisme klasse",
"Invalid mount point" : "Ongeldig aankoppelpunt",
+ "Objectstore forbidden" : "Objectopslag verboden",
"Invalid storage backend \"%s\"" : "Ongeldig opslagsysteem \"%s\"",
+ "Unsatisfied backend parameters" : "Onvoldoende backend parameters",
+ "Unsatisfied authentication mechanism parameters" : "Onvoldoende authenticatiemechanisme parameters",
+ "Admin-only storage backend \"%s\"" : "Alleen voor beheerders opslagbackend '%s\"",
"Personal" : "Persoonlijk",
"System" : "Systeem",
"Grant access" : "Sta toegang toe",
diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json
index bd3fd953a26..b5c0bf78542 100644
--- a/apps/files_external/l10n/nl.json
+++ b/apps/files_external/l10n/nl.json
@@ -1,4 +1,7 @@
{ "translations": {
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "Ophalen aanvraag tokens mislukt. Verifieer dat uw app sleutel en geheime sleutel juist zijn.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "Ophalen toegangstokens mislukt. Verifieer dat uw app sleutel en geheime sleutel juist zijn.",
+ "Please provide a valid app key and secret." : "Geef een geldige app sleutel en geheime sleutel op.",
"Step 1 failed. Exception: %s" : "Stap 1 is mislukt. Uitzondering: %s",
"Step 2 failed. Exception: %s" : "Stap 2 is mislukt. Uitzondering: %s",
"External storage" : "Externe opslag",
@@ -20,8 +23,13 @@
"SFTP with secret key login" : "SFTP met geheime sleutel inlog",
"Public key" : "Publieke sleutel",
"Storage with id \"%i\" not found" : "Opslag met id \"%i\" niet gevonden",
+ "Invalid backend or authentication mechanism class" : "Ongeldige backend of authenticatie mechanisme klasse",
"Invalid mount point" : "Ongeldig aankoppelpunt",
+ "Objectstore forbidden" : "Objectopslag verboden",
"Invalid storage backend \"%s\"" : "Ongeldig opslagsysteem \"%s\"",
+ "Unsatisfied backend parameters" : "Onvoldoende backend parameters",
+ "Unsatisfied authentication mechanism parameters" : "Onvoldoende authenticatiemechanisme parameters",
+ "Admin-only storage backend \"%s\"" : "Alleen voor beheerders opslagbackend '%s\"",
"Personal" : "Persoonlijk",
"System" : "Systeem",
"Grant access" : "Sta toegang toe",
diff --git a/apps/files_external/l10n/tr.js b/apps/files_external/l10n/tr.js
index 81418098ea0..68e69034857 100644
--- a/apps/files_external/l10n/tr.js
+++ b/apps/files_external/l10n/tr.js
@@ -1,6 +1,9 @@
OC.L10N.register(
"files_external",
{
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "Getirme istek jetonları başarısız oldu. Uygulama anahtarınızın ve gizli bilginin doğruluğunu kontrol edin.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "Getirme erişim jetonları başarısız oldu. Uygulama anahtarınızın ve gizli bilginin doğruluğunu kontrol edin.",
+ "Please provide a valid app key and secret." : "Lütfen geçerli bir uygulama anahtarı ve gizli bilgisini girin.",
"Step 1 failed. Exception: %s" : "Adım 1 başarısız. Özel durum: %s",
"Step 2 failed. Exception: %s" : "Adım 2 başarısız. Özel durum: %s",
"External storage" : "Harici depolama",
@@ -22,12 +25,19 @@ OC.L10N.register(
"SFTP with secret key login" : "Gizli anahtar oturumu ile SFTP",
"Public key" : "Ortak anahtar",
"Storage with id \"%i\" not found" : "\"%i\" kimliği ile bir depolama bulunamadı",
+ "Invalid backend or authentication mechanism class" : "Geçersiz arkauç veya kimlik doğrulama mekanizma sınıfı",
"Invalid mount point" : "Geçersiz bağlama noktası",
+ "Objectstore forbidden" : "Nesne deposu yasaktır",
"Invalid storage backend \"%s\"" : "Geçersiz depolama arka ucu \"%s\"",
+ "Unsatisfied backend parameters" : "Yetersiz arkauç parametreleri",
+ "Unsatisfied authentication mechanism parameters" : "Yetersiz kimlik doğrulama mekanizması parametreleri",
+ "Admin-only storage backend \"%s\"" : "Sadece yönetici erişimli depolama arkaucu \"%s\"",
"Personal" : "Kişisel",
"System" : "Sistem",
"Grant access" : "Erişimi sağla",
"Access granted" : "Giriş kabul edildi",
+ "Error configuring OAuth1" : "OAuth1 yapılandırma hatası",
+ "Error configuring OAuth2" : "OAuth2 yapılandırma hatası",
"Enable encryption" : "Şifrelemeyi aç",
"Enable previews" : "Önizlemeleri aç",
"Check for changes" : "Değişiklikleri denetle",
@@ -39,12 +49,19 @@ OC.L10N.register(
"Saved" : "Kaydedildi",
"Generate keys" : "Anahtarlar üret",
"Error generating key pair" : "Anahtar çifti üretirken hata",
+ "Access key" : "Erişim anahtarı",
+ "Secret key" : "Gizli anahtar",
+ "Builtin" : "Yerleşik",
"None" : "Hiçbiri",
+ "OAuth1" : "OAuth1",
"App key" : "Uyg. anahtarı",
"App secret" : "Uyg. parolası",
+ "OAuth2" : "OAuth2",
"Client ID" : "İstemci kimliği",
"Client secret" : "İstemci parolası",
+ "Username and password" : "Kullanıcı adı ve parola",
"Password" : "Parola",
+ "Session credentials" : "Oturum bilgileri",
"Amazon S3" : "Amazon S3",
"Hostname" : "Makine adı",
"Port" : "Port",
@@ -55,11 +72,15 @@ OC.L10N.register(
"URL" : "URL",
"Secure https://" : "Güvenli https://",
"Dropbox" : "Dropbox",
+ "FTP" : "FTP",
"Secure ftps://" : "Güvenli ftps://",
+ "Google Drive" : "Google Drive",
"Local" : "Yerel",
"Location" : "Konum",
"ownCloud" : "ownCloud",
+ "SFTP" : "SFTP",
"Root" : "Kök",
+ "SMB / CIFS" : "SMB / CIFS",
"<b>Note:</b> " : "<b>Not:</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>Not:</b> PHP'de cURL desteği etkin veya kurulu değil. %s bağlaması mümkün olmayacak. Lütfen kurulumu için sistem yöneticilerinizle iletişime geçin.",
"<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>Not:</b> PHP'de FTP desteği etkin veya kurulu değil. %s bağlaması mümkün olmayacak. Lütfen kurulumu için sistem yöneticilerinizle iletişime geçin.",
@@ -71,6 +92,7 @@ OC.L10N.register(
"Scope" : "Kapsam",
"External Storage" : "Harici Depolama",
"Folder name" : "Klasör ismi",
+ "Authentication" : "Kimlik Doğrulama",
"Configuration" : "Yapılandırma",
"Available for" : "Kullanabilenler",
"Advanced settings" : "Gelişmiş ayarlar",
diff --git a/apps/files_external/l10n/tr.json b/apps/files_external/l10n/tr.json
index 48349335bf4..7859e8e08dc 100644
--- a/apps/files_external/l10n/tr.json
+++ b/apps/files_external/l10n/tr.json
@@ -1,4 +1,7 @@
{ "translations": {
+ "Fetching request tokens failed. Verify that your app key and secret are correct." : "Getirme istek jetonları başarısız oldu. Uygulama anahtarınızın ve gizli bilginin doğruluğunu kontrol edin.",
+ "Fetching access tokens failed. Verify that your app key and secret are correct." : "Getirme erişim jetonları başarısız oldu. Uygulama anahtarınızın ve gizli bilginin doğruluğunu kontrol edin.",
+ "Please provide a valid app key and secret." : "Lütfen geçerli bir uygulama anahtarı ve gizli bilgisini girin.",
"Step 1 failed. Exception: %s" : "Adım 1 başarısız. Özel durum: %s",
"Step 2 failed. Exception: %s" : "Adım 2 başarısız. Özel durum: %s",
"External storage" : "Harici depolama",
@@ -20,12 +23,19 @@
"SFTP with secret key login" : "Gizli anahtar oturumu ile SFTP",
"Public key" : "Ortak anahtar",
"Storage with id \"%i\" not found" : "\"%i\" kimliği ile bir depolama bulunamadı",
+ "Invalid backend or authentication mechanism class" : "Geçersiz arkauç veya kimlik doğrulama mekanizma sınıfı",
"Invalid mount point" : "Geçersiz bağlama noktası",
+ "Objectstore forbidden" : "Nesne deposu yasaktır",
"Invalid storage backend \"%s\"" : "Geçersiz depolama arka ucu \"%s\"",
+ "Unsatisfied backend parameters" : "Yetersiz arkauç parametreleri",
+ "Unsatisfied authentication mechanism parameters" : "Yetersiz kimlik doğrulama mekanizması parametreleri",
+ "Admin-only storage backend \"%s\"" : "Sadece yönetici erişimli depolama arkaucu \"%s\"",
"Personal" : "Kişisel",
"System" : "Sistem",
"Grant access" : "Erişimi sağla",
"Access granted" : "Giriş kabul edildi",
+ "Error configuring OAuth1" : "OAuth1 yapılandırma hatası",
+ "Error configuring OAuth2" : "OAuth2 yapılandırma hatası",
"Enable encryption" : "Şifrelemeyi aç",
"Enable previews" : "Önizlemeleri aç",
"Check for changes" : "Değişiklikleri denetle",
@@ -37,12 +47,19 @@
"Saved" : "Kaydedildi",
"Generate keys" : "Anahtarlar üret",
"Error generating key pair" : "Anahtar çifti üretirken hata",
+ "Access key" : "Erişim anahtarı",
+ "Secret key" : "Gizli anahtar",
+ "Builtin" : "Yerleşik",
"None" : "Hiçbiri",
+ "OAuth1" : "OAuth1",
"App key" : "Uyg. anahtarı",
"App secret" : "Uyg. parolası",
+ "OAuth2" : "OAuth2",
"Client ID" : "İstemci kimliği",
"Client secret" : "İstemci parolası",
+ "Username and password" : "Kullanıcı adı ve parola",
"Password" : "Parola",
+ "Session credentials" : "Oturum bilgileri",
"Amazon S3" : "Amazon S3",
"Hostname" : "Makine adı",
"Port" : "Port",
@@ -53,11 +70,15 @@
"URL" : "URL",
"Secure https://" : "Güvenli https://",
"Dropbox" : "Dropbox",
+ "FTP" : "FTP",
"Secure ftps://" : "Güvenli ftps://",
+ "Google Drive" : "Google Drive",
"Local" : "Yerel",
"Location" : "Konum",
"ownCloud" : "ownCloud",
+ "SFTP" : "SFTP",
"Root" : "Kök",
+ "SMB / CIFS" : "SMB / CIFS",
"<b>Note:</b> " : "<b>Not:</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>Not:</b> PHP'de cURL desteği etkin veya kurulu değil. %s bağlaması mümkün olmayacak. Lütfen kurulumu için sistem yöneticilerinizle iletişime geçin.",
"<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>Not:</b> PHP'de FTP desteği etkin veya kurulu değil. %s bağlaması mümkün olmayacak. Lütfen kurulumu için sistem yöneticilerinizle iletişime geçin.",
@@ -69,6 +90,7 @@
"Scope" : "Kapsam",
"External Storage" : "Harici Depolama",
"Folder name" : "Klasör ismi",
+ "Authentication" : "Kimlik Doğrulama",
"Configuration" : "Yapılandırma",
"Available for" : "Kullanabilenler",
"Advanced settings" : "Gelişmiş ayarlar",
diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php
index e29b1036244..94f954178c0 100644
--- a/apps/files_external/lib/google.php
+++ b/apps/files_external/lib/google.php
@@ -248,8 +248,6 @@ class Google extends \OC\Files\Storage\Common {
}
public function opendir($path) {
- // Remove leading and trailing slashes
- $path = trim($path, '/');
$folder = $this->getDriveFile($path);
if ($folder) {
$files = array();
diff --git a/apps/files_external/service/storagesservice.php b/apps/files_external/service/storagesservice.php
index 947e544d88f..703f277d84e 100644
--- a/apps/files_external/service/storagesservice.php
+++ b/apps/files_external/service/storagesservice.php
@@ -172,7 +172,7 @@ abstract class StoragesService {
// the root mount point is in the format "/$user/files/the/mount/point"
// we remove the "/$user/files" prefix
- $parts = explode('/', trim($rootMountPath, '/'), 3);
+ $parts = explode('/', ltrim($rootMountPath, '/'), 3);
if (count($parts) < 3) {
// something went wrong, skip
\OCP\Util::writeLog(
@@ -183,7 +183,7 @@ abstract class StoragesService {
continue;
}
- $relativeMountPath = $parts[2];
+ $relativeMountPath = rtrim($parts[2], '/');
// note: we cannot do this after the loop because the decrypted config
// options might be needed for the config hash
diff --git a/apps/files_external/tests/service/globalstoragesservicetest.php b/apps/files_external/tests/service/globalstoragesservicetest.php
index 2bc480ca312..94c34c221fc 100644
--- a/apps/files_external/tests/service/globalstoragesservicetest.php
+++ b/apps/files_external/tests/service/globalstoragesservicetest.php
@@ -914,4 +914,32 @@ class GlobalStoragesServiceTest extends StoragesServiceTest {
$this->assertEquals('identifier:\Auth\Mechanism', $storage2->getAuthMechanism()->getIdentifier());
}
+ public function testReadEmptyMountPoint() {
+ $configFile = $this->dataDir . '/mount.json';
+
+ $json = [
+ 'user' => [
+ 'user1' => [
+ '/$user/files/' => [
+ 'backend' => 'identifier:\OCA\Files_External\Lib\Backend\SFTP',
+ 'authMechanism' => 'identifier:\Auth\Mechanism',
+ 'options' => [],
+ 'mountOptions' => [],
+ ],
+ ]
+ ]
+ ];
+
+ file_put_contents($configFile, json_encode($json));
+
+ $allStorages = $this->service->getAllStorages();
+
+ $this->assertCount(1, $allStorages);
+
+ $storage1 = $allStorages[1];
+
+ $this->assertEquals('/', $storage1->getMountPoint());
+ }
+
+
}
diff --git a/apps/files_external/tests/service/userglobalstoragesservicetest.php b/apps/files_external/tests/service/userglobalstoragesservicetest.php
index 49a02453840..b9e2c08c932 100644
--- a/apps/files_external/tests/service/userglobalstoragesservicetest.php
+++ b/apps/files_external/tests/service/userglobalstoragesservicetest.php
@@ -212,4 +212,9 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
$this->assertTrue(true);
}
+ public function testReadEmptyMountPoint() {
+ // we don't test this here
+ $this->assertTrue(true);
+ }
+
}
diff --git a/apps/files_sharing/api/local.php b/apps/files_sharing/api/local.php
index 87025998b3d..61b8b47d2d3 100644
--- a/apps/files_sharing/api/local.php
+++ b/apps/files_sharing/api/local.php
@@ -346,6 +346,10 @@ class Local {
}
}
}
+
+ $data['permissions'] = $share['permissions'];
+ $data['expiration'] = $share['expiration'];
+
return new \OC_OCS_Result($data);
} else {
return new \OC_OCS_Result(null, 404, "couldn't share file");
diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php
new file mode 100644
index 00000000000..d7eabb9a550
--- /dev/null
+++ b/apps/files_sharing/api/sharees.php
@@ -0,0 +1,409 @@
+<?php
+/**
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\Files_Sharing\API;
+
+use OCP\Contacts\IManager;
+use OCP\IGroup;
+use OCP\IGroupManager;
+use OCP\ILogger;
+use OCP\IRequest;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\IConfig;
+use OCP\IUserSession;
+use OCP\IURLGenerator;
+use OCP\Share;
+
+class Sharees {
+
+ /** @var IGroupManager */
+ protected $groupManager;
+
+ /** @var IUserManager */
+ protected $userManager;
+
+ /** @var IManager */
+ protected $contactsManager;
+
+ /** @var IConfig */
+ protected $config;
+
+ /** @var IUserSession */
+ protected $userSession;
+
+ /** @var IRequest */
+ protected $request;
+
+ /** @var IURLGenerator */
+ protected $urlGenerator;
+
+ /** @var ILogger */
+ protected $logger;
+
+ /** @var bool */
+ protected $shareWithGroupOnly = false;
+
+ /** @var int */
+ protected $offset = 0;
+
+ /** @var int */
+ protected $limit = 10;
+
+ /** @var array */
+ protected $result = [
+ 'exact' => [
+ 'users' => [],
+ 'groups' => [],
+ 'remotes' => [],
+ ],
+ 'users' => [],
+ 'groups' => [],
+ 'remotes' => [],
+ ];
+
+ protected $reachedEndFor = [];
+
+ /**
+ * @param IGroupManager $groupManager
+ * @param IUserManager $userManager
+ * @param IManager $contactsManager
+ * @param IConfig $config
+ * @param IUserSession $userSession
+ * @param IURLGenerator $urlGenerator
+ * @param IRequest $request
+ * @param ILogger $logger
+ */
+ public function __construct(IGroupManager $groupManager,
+ IUserManager $userManager,
+ IManager $contactsManager,
+ IConfig $config,
+ IUserSession $userSession,
+ IURLGenerator $urlGenerator,
+ IRequest $request,
+ ILogger $logger) {
+ $this->groupManager = $groupManager;
+ $this->userManager = $userManager;
+ $this->contactsManager = $contactsManager;
+ $this->config = $config;
+ $this->userSession = $userSession;
+ $this->urlGenerator = $urlGenerator;
+ $this->request = $request;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @param string $search
+ */
+ protected function getUsers($search) {
+ $this->result['users'] = $this->result['exact']['users'] = $users = [];
+
+ if ($this->shareWithGroupOnly) {
+ // Search in all the groups this user is part of
+ $userGroups = $this->groupManager->getUserGroupIds($this->userSession->getUser());
+ foreach ($userGroups as $userGroup) {
+ $usersTmp = $this->groupManager->displayNamesInGroup($userGroup, $search, $this->limit, $this->offset);
+ foreach ($usersTmp as $uid => $userDisplayName) {
+ $users[$uid] = $userDisplayName;
+ }
+ }
+ } else {
+ // Search in all users
+ $usersTmp = $this->userManager->searchDisplayName($search, $this->limit, $this->offset);
+
+ foreach ($usersTmp as $user) {
+ $users[$user->getUID()] = $user->getDisplayName();
+ }
+ }
+
+ if (sizeof($users) < $this->limit) {
+ $this->reachedEndFor[] = 'users';
+ }
+
+ $foundUserById = false;
+ foreach ($users as $uid => $userDisplayName) {
+ if (strtolower($uid) === $search || strtolower($userDisplayName) === $search) {
+ if (strtolower($uid) === $search) {
+ $foundUserById = true;
+ }
+ $this->result['exact']['users'][] = [
+ 'label' => $userDisplayName,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $uid,
+ ],
+ ];
+ } else {
+ $this->result['users'][] = [
+ 'label' => $userDisplayName,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $uid,
+ ],
+ ];
+ }
+ }
+
+ if ($this->offset === 0 && !$foundUserById) {
+ // On page one we try if the search result has a direct hit on the
+ // user id and if so, we add that to the exact match list
+ $user = $this->userManager->get($search);
+ if ($user instanceof IUser) {
+ array_push($this->result['exact']['users'], [
+ 'label' => $user->getDisplayName(),
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_USER,
+ 'shareWith' => $user->getUID(),
+ ],
+ ]);
+ }
+ }
+ }
+
+ /**
+ * @param string $search
+ */
+ protected function getGroups($search) {
+ $this->result['groups'] = $this->result['exact']['groups'] = [];
+
+ $groups = $this->groupManager->search($search, $this->limit, $this->offset);
+ $groups = array_map(function (IGroup $group) { return $group->getGID(); }, $groups);
+
+ if (sizeof($groups) < $this->limit) {
+ $this->reachedEndFor[] = 'groups';
+ }
+
+ $userGroups = [];
+ if (!empty($groups) && $this->shareWithGroupOnly) {
+ // Intersect all the groups that match with the groups this user is a member of
+ $userGroups = $this->groupManager->getUserGroups($this->userSession->getUser());
+ $userGroups = array_map(function (IGroup $group) { return $group->getGID(); }, $userGroups);
+ $groups = array_intersect($groups, $userGroups);
+ }
+
+ foreach ($groups as $gid) {
+ if (strtolower($gid) === $search) {
+ $this->result['exact']['groups'][] = [
+ 'label' => $search,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_GROUP,
+ 'shareWith' => $search,
+ ],
+ ];
+ } else {
+ $this->result['groups'][] = [
+ 'label' => $gid,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_GROUP,
+ 'shareWith' => $gid,
+ ],
+ ];
+ }
+ }
+
+ if ($this->offset === 0 && empty($this->result['exact']['groups'])) {
+ // On page one we try if the search result has a direct hit on the
+ // user id and if so, we add that to the exact match list
+ $group = $this->groupManager->get($search);
+ if ($group instanceof IGroup && (!$this->shareWithGroupOnly || in_array($group->getGID(), $userGroups))) {
+ array_push($this->result['exact']['groups'], [
+ 'label' => $group->getGID(),
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_GROUP,
+ 'shareWith' => $group->getGID(),
+ ],
+ ]);
+ }
+ }
+ }
+
+ /**
+ * @param string $search
+ * @return array possible sharees
+ */
+ protected function getRemote($search) {
+ $this->result['remotes'] = [];
+
+ // Search in contacts
+ //@todo Pagination missing
+ $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
+ $foundRemoteById = false;
+ foreach ($addressBookContacts as $contact) {
+ if (isset($contact['CLOUD'])) {
+ foreach ($contact['CLOUD'] as $cloudId) {
+ if (strtolower($contact['FN']) === $search || strtolower($cloudId) === $search) {
+ if (strtolower($cloudId) === $search) {
+ $foundRemoteById = true;
+ }
+ $this->result['exact']['remotes'][] = [
+ 'label' => $contact['FN'],
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $cloudId,
+ ],
+ ];
+ } else {
+ $this->result['remotes'][] = [
+ 'label' => $contact['FN'],
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $cloudId,
+ ],
+ ];
+ }
+ }
+ }
+ }
+
+ if (!$foundRemoteById && substr_count($search, '@') >= 1 && substr_count($search, ' ') === 0 && $this->offset === 0) {
+ $this->result['exact']['remotes'][] = [
+ 'label' => $search,
+ 'value' => [
+ 'shareType' => Share::SHARE_TYPE_REMOTE,
+ 'shareWith' => $search,
+ ],
+ ];
+ }
+
+ $this->reachedEndFor[] = 'remotes';
+ }
+
+ /**
+ * @return \OC_OCS_Result
+ */
+ public function search() {
+ $search = isset($_GET['search']) ? (string) $_GET['search'] : '';
+ $itemType = isset($_GET['itemType']) ? (string) $_GET['itemType'] : null;
+ $page = !empty($_GET['page']) ? max(1, (int) $_GET['page']) : 1;
+ $perPage = !empty($_GET['limit']) ? max(1, (int) $_GET['limit']) : 200;
+
+ $shareTypes = [
+ Share::SHARE_TYPE_USER,
+ Share::SHARE_TYPE_GROUP,
+ Share::SHARE_TYPE_REMOTE,
+ ];
+ if (isset($_GET['shareType']) && is_array($_GET['shareType'])) {
+ $shareTypes = array_intersect($shareTypes, $_GET['shareType']);
+ sort($shareTypes);
+
+ } else if (isset($_GET['shareType']) && is_numeric($_GET['shareType'])) {
+ $shareTypes = array_intersect($shareTypes, [(int) $_GET['shareType']]);
+ sort($shareTypes);
+ }
+
+ if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes) && !$this->isRemoteSharingAllowed($itemType)) {
+ // Remove remote shares from type array, because it is not allowed.
+ $shareTypes = array_diff($shareTypes, [Share::SHARE_TYPE_REMOTE]);
+ }
+
+ $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes';
+ $this->limit = (int) $perPage;
+ $this->offset = $perPage * ($page - 1);
+
+ return $this->searchSharees(strtolower($search), $itemType, $shareTypes, $page, $perPage);
+ }
+
+ /**
+ * Method to get out the static call for better testing
+ *
+ * @param string $itemType
+ * @return bool
+ */
+ protected function isRemoteSharingAllowed($itemType) {
+ try {
+ $backend = Share::getBackend($itemType);
+ return $backend->isShareTypeAllowed(Share::SHARE_TYPE_REMOTE);
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Testable search function that does not need globals
+ *
+ * @param string $search
+ * @param string $itemType
+ * @param array $shareTypes
+ * @param int $page
+ * @param int $perPage
+ * @return \OC_OCS_Result
+ */
+ protected function searchSharees($search, $itemType, array $shareTypes, $page, $perPage) {
+ // Verify arguments
+ if ($itemType === null) {
+ return new \OC_OCS_Result(null, 400, 'missing itemType');
+ }
+
+ // Get users
+ if (in_array(Share::SHARE_TYPE_USER, $shareTypes)) {
+ $this->getUsers($search);
+ }
+
+ // Get groups
+ if (in_array(Share::SHARE_TYPE_GROUP, $shareTypes)) {
+ $this->getGroups($search);
+ }
+
+ // Get remote
+ if (in_array(Share::SHARE_TYPE_REMOTE, $shareTypes)) {
+ $this->getRemote($search);
+ }
+
+ $response = new \OC_OCS_Result($this->result);
+ $response->setItemsPerPage($perPage);
+
+ if (sizeof($this->reachedEndFor) < 3) {
+ $response->addHeader('Link', $this->getPaginationLink($page, [
+ 'search' => $search,
+ 'itemType' => $itemType,
+ 'shareType' => $shareTypes,
+ 'limit' => $perPage,
+ ]));
+ }
+
+ return $response;
+ }
+
+ /**
+ * Generates a bunch of pagination links for the current page
+ *
+ * @param int $page Current page
+ * @param array $params Parameters for the URL
+ * @return string
+ */
+ protected function getPaginationLink($page, array $params) {
+ if ($this->isV2()) {
+ $url = $this->urlGenerator->getAbsoluteURL('/ocs/v2.php/apps/files_sharing/api/v1/sharees') . '?';
+ } else {
+ $url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?';
+ }
+ $params['page'] = $page + 1;
+ $link = '<' . $url . http_build_query($params) . '>; rel="next"';
+
+ return $link;
+ }
+
+ /**
+ * @return bool
+ */
+ protected function isV2() {
+ return $this->request->getScriptName() === '/ocs/v2.php';
+ }
+}
diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php
index 184ad29bba4..375124cb730 100644
--- a/apps/files_sharing/appinfo/routes.php
+++ b/apps/files_sharing/appinfo/routes.php
@@ -102,3 +102,16 @@ API::register('delete',
array('\OCA\Files_Sharing\API\Remote', 'declineShare'),
'files_sharing');
+$sharees = new \OCA\Files_Sharing\API\Sharees(\OC::$server->getGroupManager(),
+ \OC::$server->getUserManager(),
+ \OC::$server->getContactsManager(),
+ \OC::$server->getConfig(),
+ \OC::$server->getUserSession(),
+ \OC::$server->getURLGenerator(),
+ \OC::$server->getRequest(),
+ \OC::$server->getLogger());
+
+API::register('get',
+ '/apps/files_sharing/api/v1/sharees',
+ [$sharees, 'search'],
+ 'files_sharing', API::USER_AUTH);
diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php
index d0ee71cec5a..3809b812051 100644
--- a/apps/files_sharing/tests/api.php
+++ b/apps/files_sharing/tests/api.php
@@ -73,40 +73,108 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
*/
- function testCreateShare() {
+ function testCreateShareUserFile() {
+ // simulate a post request
+ $_POST['path'] = $this->filename;
+ $_POST['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2;
+ $_POST['shareType'] = \OCP\Share::SHARE_TYPE_USER;
+
+ $result = \OCA\Files_Sharing\API\Local::createShare([]);
+
+ $this->assertTrue($result->succeeded());
+ $data = $result->getData();
+ $this->assertEquals(23, $data['permissions']);
+ $this->assertEmpty($data['expiration']);
+
+ $share = $this->getShareFromId($data['id']);
+ $items = \OCP\Share::getItemShared('file', $share['item_source']);
+ $this->assertTrue(!empty($items));
- // share to user
+ $fileinfo = $this->view->getFileInfo($this->filename);
+ \OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2);
+ }
+ function testCreateShareUserFolder() {
// simulate a post request
- $_POST['path'] = $this->filename;
+ $_POST['path'] = $this->folder;
$_POST['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2;
$_POST['shareType'] = \OCP\Share::SHARE_TYPE_USER;
- $result = \OCA\Files_Sharing\API\Local::createShare(array());
+ $result = \OCA\Files_Sharing\API\Local::createShare([]);
$this->assertTrue($result->succeeded());
$data = $result->getData();
+ $this->assertEquals(31, $data['permissions']);
+ $this->assertEmpty($data['expiration']);
$share = $this->getShareFromId($data['id']);
+ $items = \OCP\Share::getItemShared('file', $share['item_source']);
+ $this->assertTrue(!empty($items));
+
+ $fileinfo = $this->view->getFileInfo($this->folder);
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2);
+ }
+
+
+ function testCreateShareGroupFile() {
+ // simulate a post request
+ $_POST['path'] = $this->filename;
+ $_POST['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_GROUP1;
+ $_POST['shareType'] = \OCP\Share::SHARE_TYPE_GROUP;
+
+ $result = \OCA\Files_Sharing\API\Local::createShare([]);
+ $this->assertTrue($result->succeeded());
+ $data = $result->getData();
+ $this->assertEquals(23, $data['permissions']);
+ $this->assertEmpty($data['expiration']);
+
+ $share = $this->getShareFromId($data['id']);
$items = \OCP\Share::getItemShared('file', $share['item_source']);
+ $this->assertTrue(!empty($items));
+
+ $fileinfo = $this->view->getFileInfo($this->filename);
+ \OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP,
+ \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_GROUP1);
+ }
+
+ function testCreateShareGroupFolder() {
+ // simulate a post request
+ $_POST['path'] = $this->folder;
+ $_POST['shareWith'] = \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_GROUP1;
+ $_POST['shareType'] = \OCP\Share::SHARE_TYPE_GROUP;
+
+ $result = \OCA\Files_Sharing\API\Local::createShare([]);
+
+ $this->assertTrue($result->succeeded());
+ $data = $result->getData();
+ $this->assertEquals(31, $data['permissions']);
+ $this->assertEmpty($data['expiration']);
+ $share = $this->getShareFromId($data['id']);
+ $items = \OCP\Share::getItemShared('file', $share['item_source']);
$this->assertTrue(!empty($items));
- // share link
+ $fileinfo = $this->view->getFileInfo($this->folder);
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP,
+ \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_GROUP1);
+ }
+ public function testCreateShareLink() {
// simulate a post request
$_POST['path'] = $this->folder;
$_POST['shareType'] = \OCP\Share::SHARE_TYPE_LINK;
- $result = \OCA\Files_Sharing\API\Local::createShare(array());
+ $result = \OCA\Files_Sharing\API\Local::createShare([]);
// check if API call was successful
$this->assertTrue($result->succeeded());
$data = $result->getData();
-
- // check if we have a token
+ $this->assertEquals(1, $data['permissions']);
+ $this->assertEmpty($data['expiration']);
$this->assertTrue(is_string($data['token']));
// check for correct link
@@ -115,18 +183,39 @@ class Test_Files_Sharing_Api extends TestCase {
$share = $this->getShareFromId($data['id']);
-
$items = \OCP\Share::getItemShared('file', $share['item_source']);
-
$this->assertTrue(!empty($items));
- $fileinfo = $this->view->getFileInfo($this->filename);
+ $fileinfo = $this->view->getFileInfo($this->folder);
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null);
+ }
- \OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
- \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2);
+ public function testCreateShareLinkPublicUpload() {
+ // simulate a post request
+ $_POST['path'] = $this->folder;
+ $_POST['shareType'] = \OCP\Share::SHARE_TYPE_LINK;
+ $_POST['publicUpload'] = 'true';
- $fileinfo = $this->view->getFileInfo($this->folder);
+ $result = \OCA\Files_Sharing\API\Local::createShare(array());
+
+ // check if API call was successful
+ $this->assertTrue($result->succeeded());
+
+ $data = $result->getData();
+ $this->assertEquals(7, $data['permissions']);
+ $this->assertEmpty($data['expiration']);
+ $this->assertTrue(is_string($data['token']));
+ // check for correct link
+ $url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']);
+ $this->assertEquals($url, $data['url']);
+
+
+ $share = $this->getShareFromId($data['id']);
+ $items = \OCP\Share::getItemShared('file', $share['item_source']);
+ $this->assertTrue(!empty($items));
+
+ $fileinfo = $this->view->getFileInfo($this->folder);
\OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null);
}
@@ -287,7 +376,7 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
*/
function testGetAllShares() {
@@ -334,7 +423,7 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareLink
*/
function testPublicLinkUrl() {
// simulate a post request
@@ -379,7 +468,8 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
+ * @depends testCreateShareLink
*/
function testGetShareFromSource() {
@@ -409,7 +499,8 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
+ * @depends testCreateShareLink
*/
function testGetShareFromSourceWithReshares() {
@@ -463,7 +554,7 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
*/
function testGetShareFromId() {
@@ -911,7 +1002,8 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
+ * @depends testCreateShareLink
*/
function testUpdateShare() {
@@ -1037,7 +1129,7 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
*/
public function testUpdateShareInvalidPermissions() {
@@ -1232,7 +1324,7 @@ class Test_Files_Sharing_Api extends TestCase {
/**
* @medium
- * @depends testCreateShare
+ * @depends testCreateShareUserFile
*/
function testDeleteShare() {
@@ -1526,6 +1618,7 @@ class Test_Files_Sharing_Api extends TestCase {
$data = $result->getData();
$this->assertTrue(is_string($data['token']));
+ $this->assertEquals($date, substr($data['expiration'], 0, 10));
// check for correct link
$url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']);
@@ -1564,6 +1657,7 @@ class Test_Files_Sharing_Api extends TestCase {
$data = $result->getData();
$this->assertTrue(is_string($data['token']));
+ $this->assertEquals($date->format('Y-m-d') . ' 00:00:00', $data['expiration']);
// check for correct link
$url = \OC::$server->getURLGenerator()->getAbsoluteURL('/index.php/s/' . $data['token']);
diff --git a/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php
new file mode 100644
index 00000000000..1e4438acd88
--- /dev/null
+++ b/apps/files_sharing/tests/api/shareestest.php
@@ -0,0 +1,995 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Files_Sharing\Tests\API;
+
+use Doctrine\DBAL\Connection;
+use OC\Share\Constants;
+use OCA\Files_Sharing\API\Sharees;
+use OCA\Files_sharing\Tests\TestCase;
+use OCP\Share;
+
+class ShareesTest extends TestCase {
+ /** @var Sharees */
+ protected $sharees;
+
+ /** @var \OCP\IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $userManager;
+
+ /** @var \OCP\IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $groupManager;
+
+ /** @var \OCP\Contacts\IManager|\PHPUnit_Framework_MockObject_MockObject */
+ protected $contactsManager;
+
+ /** @var \OCP\IUserSession|\PHPUnit_Framework_MockObject_MockObject */
+ protected $session;
+
+ /** @var \OCP\IRequest|\PHPUnit_Framework_MockObject_MockObject */
+ protected $request;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->userManager = $this->getMockBuilder('OCP\IUserManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->groupManager = $this->getMockBuilder('OCP\IGroupManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->contactsManager = $this->getMockBuilder('OCP\Contacts\IManager')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->session = $this->getMockBuilder('OCP\IUserSession')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->request = $this->getMockBuilder('OCP\IRequest')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->sharees = new Sharees(
+ $this->groupManager,
+ $this->userManager,
+ $this->contactsManager,
+ $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(),
+ $this->session,
+ $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
+ $this->request,
+ $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock()
+ );
+ }
+
+ protected function getUserMock($uid, $displayName) {
+ $user = $this->getMockBuilder('OCP\IUser')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $user->expects($this->any())
+ ->method('getUID')
+ ->willReturn($uid);
+
+ $user->expects($this->any())
+ ->method('getDisplayName')
+ ->willReturn($displayName);
+
+ return $user;
+ }
+
+ protected function getGroupMock($gid) {
+ $group = $this->getMockBuilder('OCP\IGroup')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $group->expects($this->any())
+ ->method('getGID')
+ ->willReturn($gid);
+
+ return $group;
+ }
+
+ public function dataGetUsers() {
+ return [
+ ['test', false, [], [], [], [], true, false],
+ ['test', true, [], [], [], [], true, false],
+ [
+ 'test', false, [], [],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test', true, [], [],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ], [], true, $this->getUserMock('test', 'Test')
+ ],
+ [
+ 'test',
+ false,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ [],
+ [
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ false,
+ [],
+ [
+ $this->getUserMock('test0', 'Test'),
+ $this->getUserMock('test1', 'Test One'),
+ $this->getUserMock('test2', 'Test Two'),
+ ],
+ [
+ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']],
+ ],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, ['test1' => 'Test One']],
+ ['xyz', 'test', 2, 0, []],
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ true,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test1' => 'Test One',
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ [
+ 'test',
+ true,
+ ['abc', 'xyz'],
+ [
+ ['abc', 'test', 2, 0, [
+ 'test' => 'Test One',
+ ]],
+ ['xyz', 'test', 2, 0, [
+ 'test2' => 'Test Two',
+ ]],
+ ],
+ [
+ ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'Test Two', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ false,
+ false,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetUsers
+ *
+ * @param string $searchTerm
+ * @param bool $shareWithGroupOnly
+ * @param array $groupResponse
+ * @param array $userResponse
+ * @param array $exactExpected
+ * @param array $expected
+ * @param bool $reachedEnd
+ * @param mixed $singleUser
+ */
+ public function testGetUsers($searchTerm, $shareWithGroupOnly, $groupResponse, $userResponse, $exactExpected, $expected, $reachedEnd, $singleUser) {
+ $this->invokePrivate($this->sharees, 'limit', [2]);
+ $this->invokePrivate($this->sharees, 'offset', [0]);
+ $this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]);
+
+ $user = $this->getUserMock('admin', 'Administrator');
+ $this->session->expects($this->any())
+ ->method('getUser')
+ ->willReturn($user);
+
+ if (!$shareWithGroupOnly) {
+ $this->userManager->expects($this->once())
+ ->method('searchDisplayName')
+ ->with($searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
+ ->willReturn($userResponse);
+ } else {
+ $this->groupManager->expects($this->once())
+ ->method('getUserGroupIds')
+ ->with($user)
+ ->willReturn($groupResponse);
+
+ $this->groupManager->expects($this->exactly(sizeof($groupResponse)))
+ ->method('displayNamesInGroup')
+ ->with($this->anything(), $searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
+ ->willReturnMap($userResponse);
+ }
+
+ if ($singleUser !== false) {
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->with($searchTerm)
+ ->willReturn($singleUser);
+ }
+
+ $this->invokePrivate($this->sharees, 'getUsers', [$searchTerm]);
+ $result = $this->invokePrivate($this->sharees, 'result');
+
+ $this->assertEquals($exactExpected, $result['exact']['users']);
+ $this->assertEquals($expected, $result['users']);
+ $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
+ }
+
+ public function dataGetGroups() {
+ return [
+ ['test', false, [], [], [], [], true, false],
+ [
+ 'test', false,
+ [$this->getGroupMock('test1')],
+ [],
+ [],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ true,
+ false,
+ ],
+ [
+ 'test', false,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ null,
+ ],
+ [
+ 'test', false,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ $this->getGroupMock('test'),
+ ],
+ ['test', true, [], [], [], [], true, false],
+ [
+ 'test', true,
+ [
+ $this->getGroupMock('test1'),
+ $this->getGroupMock('test2'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [],
+ false,
+ false,
+ ],
+ [
+ 'test', true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test1')],
+ [],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', true,
+ [
+ $this->getGroupMock('test'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]],
+ [['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']]],
+ false,
+ false,
+ ],
+ [
+ 'test', true,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ null,
+ ],
+ [
+ 'test', true,
+ [
+ $this->getGroupMock('test0'),
+ $this->getGroupMock('test1'),
+ ],
+ [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')],
+ [
+ ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']],
+ ],
+ [
+ ['label' => 'test0', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test0']],
+ ['label' => 'test1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test1']],
+ ],
+ false,
+ $this->getGroupMock('test'),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetGroups
+ *
+ * @param string $searchTerm
+ * @param bool $shareWithGroupOnly
+ * @param array $groupResponse
+ * @param array $userGroupsResponse
+ * @param array $exactExpected
+ * @param array $expected
+ * @param bool $reachedEnd
+ * @param mixed $singleGroup
+ */
+ public function testGetGroups($searchTerm, $shareWithGroupOnly, $groupResponse, $userGroupsResponse, $exactExpected, $expected, $reachedEnd, $singleGroup) {
+ $this->invokePrivate($this->sharees, 'limit', [2]);
+ $this->invokePrivate($this->sharees, 'offset', [0]);
+ $this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]);
+
+ $this->groupManager->expects($this->once())
+ ->method('search')
+ ->with($searchTerm, $this->invokePrivate($this->sharees, 'limit'), $this->invokePrivate($this->sharees, 'offset'))
+ ->willReturn($groupResponse);
+
+ if ($singleGroup !== false) {
+ $this->groupManager->expects($this->once())
+ ->method('get')
+ ->with($searchTerm)
+ ->willReturn($singleGroup);
+ }
+
+ if ($shareWithGroupOnly) {
+ $user = $this->getUserMock('admin', 'Administrator');
+ $this->session->expects($this->any())
+ ->method('getUser')
+ ->willReturn($user);
+
+ $numGetUserGroupsCalls = empty($groupResponse) ? 0 : 1;
+ $this->groupManager->expects($this->exactly($numGetUserGroupsCalls))
+ ->method('getUserGroups')
+ ->with($user)
+ ->willReturn($userGroupsResponse);
+ }
+
+ $this->invokePrivate($this->sharees, 'getGroups', [$searchTerm]);
+ $result = $this->invokePrivate($this->sharees, 'result');
+
+ $this->assertEquals($exactExpected, $result['exact']['groups']);
+ $this->assertEquals($expected, $result['groups']);
+ $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
+ }
+
+ public function dataGetRemote() {
+ return [
+ ['test', [], [], [], true],
+ [
+ 'test@remote',
+ [],
+ [
+ ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
+ ],
+ [],
+ true,
+ ],
+ [
+ 'test',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ [],
+ [
+ ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']],
+ ],
+ true,
+ ],
+ [
+ 'test@remote',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ [
+ ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']],
+ ],
+ [
+ ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']],
+ ],
+ true,
+ ],
+ [
+ 'username@localhost',
+ [
+ [
+ 'FN' => 'User3 @ Localhost',
+ ],
+ [
+ 'FN' => 'User2 @ Localhost',
+ 'CLOUD' => [
+ ],
+ ],
+ [
+ 'FN' => 'User @ Localhost',
+ 'CLOUD' => [
+ 'username@localhost',
+ ],
+ ],
+ ],
+ [
+ ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']],
+ ],
+ [
+ ],
+ true,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetRemote
+ *
+ * @param string $searchTerm
+ * @param array $contacts
+ * @param array $exactExpected
+ * @param array $expected
+ * @param bool $reachedEnd
+ */
+ public function testGetRemote($searchTerm, $contacts, $exactExpected, $expected, $reachedEnd) {
+ $this->contactsManager->expects($this->any())
+ ->method('search')
+ ->with($searchTerm, ['CLOUD', 'FN'])
+ ->willReturn($contacts);
+
+ $this->invokePrivate($this->sharees, 'getRemote', [$searchTerm]);
+ $result = $this->invokePrivate($this->sharees, 'result');
+
+ $this->assertEquals($exactExpected, $result['exact']['remotes']);
+ $this->assertEquals($expected, $result['remotes']);
+ $this->assertCount((int) $reachedEnd, $this->invokePrivate($this->sharees, 'reachedEndFor'));
+ }
+
+ public function dataSearch() {
+ $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE];
+
+ return [
+ [[], '', true, '', null, $allTypes, 1, 200, false],
+
+ // Test itemType
+ [[
+ 'search' => '',
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'search' => 'foobar',
+ ], '', true, 'foobar', null, $allTypes, 1, 200, false],
+ [[
+ 'search' => 0,
+ ], '', true, '0', null, $allTypes, 1, 200, false],
+
+ // Test itemType
+ [[
+ 'itemType' => '',
+ ], '', true, '', '', $allTypes, 1, 200, false],
+ [[
+ 'itemType' => 'folder',
+ ], '', true, '', 'folder', $allTypes, 1, 200, false],
+ [[
+ 'itemType' => 0,
+ ], '', true, '', '0', $allTypes, 1, 200, false],
+
+ // Test shareType
+ [[
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'shareType' => 0,
+ ], '', true, '', null, [0], 1, 200, false],
+ [[
+ 'shareType' => '0',
+ ], '', true, '', null, [0], 1, 200, false],
+ [[
+ 'shareType' => 1,
+ ], '', true, '', null, [1], 1, 200, false],
+ [[
+ 'shareType' => 12,
+ ], '', true, '', null, [], 1, 200, false],
+ [[
+ 'shareType' => 'foobar',
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'shareType' => [0, 1, 2],
+ ], '', true, '', null, [0, 1], 1, 200, false],
+ [[
+ 'shareType' => [0, 1],
+ ], '', true, '', null, [0, 1], 1, 200, false],
+ [[
+ 'shareType' => $allTypes,
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'shareType' => $allTypes,
+ ], '', false, '', null, [0, 1], 1, 200, false],
+
+ // Test pagination
+ [[
+ 'page' => 0,
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'page' => '0',
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'page' => -1,
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'page' => 1,
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'page' => 10,
+ ], '', true, '', null, $allTypes, 10, 200, false],
+
+ // Test limit
+ [[
+ 'limit' => 0,
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'limit' => '0',
+ ], '', true, '', null, $allTypes, 1, 200, false],
+ [[
+ 'limit' => -1,
+ ], '', true, '', null, $allTypes, 1, 1, false],
+ [[
+ 'limit' => 1,
+ ], '', true, '', null, $allTypes, 1, 1, false],
+ [[
+ 'limit' => 10,
+ ], '', true, '', null, $allTypes, 1, 10, false],
+
+ // Test $shareWithGroupOnly setting
+ [[], 'no', true, '', null, $allTypes, 1, 200, false],
+ [[], 'yes', true, '', null, $allTypes, 1, 200, true],
+
+ ];
+ }
+
+ /**
+ * @dataProvider dataSearch
+ *
+ * @param array $getData
+ * @param string $apiSetting
+ * @param bool $remoteSharingEnabled
+ * @param string $search
+ * @param string $itemType
+ * @param array $shareTypes
+ * @param int $page
+ * @param int $perPage
+ * @param bool $shareWithGroupOnly
+ */
+ public function testSearch($getData, $apiSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly) {
+ $oldGet = $_GET;
+ $_GET = $getData;
+
+ $config = $this->getMockBuilder('OCP\IConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $config->expects($this->once())
+ ->method('getAppValue')
+ ->with('core', 'shareapi_only_share_with_group_members', 'no')
+ ->willReturn($apiSetting);
+
+ $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees')
+ ->setConstructorArgs([
+ $this->groupManager,
+ $this->userManager,
+ $this->contactsManager,
+ $config,
+ $this->session,
+ $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock()
+ ])
+ ->setMethods(array('searchSharees', 'isRemoteSharingAllowed'))
+ ->getMock();
+ $sharees->expects($this->once())
+ ->method('searchSharees')
+ ->with($search, $itemType, $shareTypes, $page, $perPage)
+ ->willReturnCallback(function
+ ($isearch, $iitemType, $ishareTypes, $ipage, $iperPage)
+ use ($search, $itemType, $shareTypes, $page, $perPage) {
+
+ // We are doing strict comparisons here, so we can differ 0/'' and null on shareType/itemType
+ $this->assertSame($search, $isearch);
+ $this->assertSame($itemType, $iitemType);
+ $this->assertSame($shareTypes, $ishareTypes);
+ $this->assertSame($page, $ipage);
+ $this->assertSame($perPage, $iperPage);
+ return new \OC_OCS_Result([]);
+ });
+ $sharees->expects($this->any())
+ ->method('isRemoteSharingAllowed')
+ ->with($itemType)
+ ->willReturn($remoteSharingEnabled);
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */
+ $this->assertInstanceOf('\OC_OCS_Result', $sharees->search());
+
+ $this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly'));
+
+ $_GET = $oldGet;
+ }
+
+ public function dataIsRemoteSharingAllowed() {
+ return [
+ ['file', true],
+ ['folder', true],
+ ['', false],
+ ['contacts', false],
+ ];
+ }
+
+ /**
+ * @dataProvider dataIsRemoteSharingAllowed
+ *
+ * @param string $itemType
+ * @param bool $expected
+ */
+ public function testIsRemoteSharingAllowed($itemType, $expected) {
+ $this->assertSame($expected, $this->invokePrivate($this->sharees, 'isRemoteSharingAllowed', [$itemType]));
+ }
+
+ public function dataSearchSharees() {
+ return [
+ ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], [],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [],
+ 'groups' => [],
+ 'remotes' => [],
+ ], false],
+ ['test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [], [], [],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [],
+ 'groups' => [],
+ 'remotes' => [],
+ ], false],
+ [
+ 'test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE], 1, 2, false, [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ], [
+ ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
+ ], [
+ ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
+ ],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ 'groups' => [
+ ['label' => 'testgroup1', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'testgroup1']],
+ ],
+ 'remotes' => [
+ ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
+ ],
+ ], true,
+ ],
+ // No groups requested
+ [
+ 'test', 'folder', [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_REMOTE], 1, 2, false, [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ], null, [
+ ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
+ ],
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ 'groups' => [],
+ 'remotes' => [
+ ['label' => 'testz@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'testz@remote']],
+ ],
+ ], false,
+ ],
+ // Share type restricted to user - Only one user
+ [
+ 'test', 'folder', [Share::SHARE_TYPE_USER], 1, 2, false, [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ], null, null,
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [
+ ['label' => 'test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ],
+ 'groups' => [],
+ 'remotes' => [],
+ ], false,
+ ],
+ // Share type restricted to user - Multipage result
+ [
+ 'test', 'folder', [Share::SHARE_TYPE_USER], 1, 2, false, [
+ ['label' => 'test 1', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'test 2', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ], null, null,
+ [
+ 'exact' => ['users' => [], 'groups' => [], 'remotes' => []],
+ 'users' => [
+ ['label' => 'test 1', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test1']],
+ ['label' => 'test 2', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test2']],
+ ],
+ 'groups' => [],
+ 'remotes' => [],
+ ], true,
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataSearchSharees
+ *
+ * @param string $searchTerm
+ * @param string $itemType
+ * @param array $shareTypes
+ * @param int $page
+ * @param int $perPage
+ * @param bool $shareWithGroupOnly
+ * @param array $mockedUserResult
+ * @param array $mockedGroupsResult
+ * @param array $mockedRemotesResult
+ * @param array $expected
+ * @param bool $nextLink
+ */
+ public function testSearchSharees($searchTerm, $itemType, array $shareTypes, $page, $perPage, $shareWithGroupOnly,
+ $mockedUserResult, $mockedGroupsResult, $mockedRemotesResult, $expected, $nextLink) {
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */
+ $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees')
+ ->setConstructorArgs([
+ $this->groupManager,
+ $this->userManager,
+ $this->contactsManager,
+ $this->getMockBuilder('OCP\IConfig')->disableOriginalConstructor()->getMock(),
+ $this->session,
+ $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock()
+ ])
+ ->setMethods(array('getShareesForShareIds', 'getUsers', 'getGroups', 'getRemote'))
+ ->getMock();
+ $sharees->expects(($mockedUserResult === null) ? $this->never() : $this->once())
+ ->method('getUsers')
+ ->with($searchTerm)
+ ->willReturnCallback(function() use ($sharees, $mockedUserResult) {
+ $result = $this->invokePrivate($sharees, 'result');
+ $result['users'] = $mockedUserResult;
+ $this->invokePrivate($sharees, 'result', [$result]);
+ });
+ $sharees->expects(($mockedGroupsResult === null) ? $this->never() : $this->once())
+ ->method('getGroups')
+ ->with($searchTerm)
+ ->willReturnCallback(function() use ($sharees, $mockedGroupsResult) {
+ $result = $this->invokePrivate($sharees, 'result');
+ $result['groups'] = $mockedGroupsResult;
+ $this->invokePrivate($sharees, 'result', [$result]);
+ });
+ $sharees->expects(($mockedRemotesResult === null) ? $this->never() : $this->once())
+ ->method('getRemote')
+ ->with($searchTerm)
+ ->willReturnCallback(function() use ($sharees, $mockedRemotesResult) {
+ $result = $this->invokePrivate($sharees, 'result');
+ $result['remotes'] = $mockedRemotesResult;
+ $this->invokePrivate($sharees, 'result', [$result]);
+ });
+
+ /** @var \OC_OCS_Result $ocs */
+ $ocs = $this->invokePrivate($sharees, 'searchSharees', [$searchTerm, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly]);
+ $this->assertInstanceOf('\OC_OCS_Result', $ocs);
+ $this->assertEquals($expected, $ocs->getData());
+
+ // Check if next link is set
+ if ($nextLink) {
+ $headers = $ocs->getHeaders();
+ $this->assertArrayHasKey('Link', $headers);
+ $this->assertStringStartsWith('<', $headers['Link']);
+ $this->assertStringEndsWith('>; rel="next"', $headers['Link']);
+ }
+ }
+
+ public function testSearchShareesNoItemType() {
+ /** @var \OC_OCS_Result $ocs */
+ $ocs = $this->invokePrivate($this->sharees, 'searchSharees', ['', null, [], [], 0, 0, false]);
+ $this->assertInstanceOf('\OC_OCS_Result', $ocs);
+
+ $this->assertSame(400, $ocs->getStatusCode(), 'Expected status code 400');
+ $this->assertSame([], $ocs->getData(), 'Expected that no data is send');
+
+ $meta = $ocs->getMeta();
+ $this->assertNotEmpty($meta);
+ $this->assertArrayHasKey('message', $meta);
+ $this->assertSame('missing itemType', $meta['message']);
+ }
+
+ public function dataGetPaginationLink() {
+ return [
+ [1, '/ocs/v1.php', ['limit' => 2], '<?limit=2&page=2>; rel="next"'],
+ [10, '/ocs/v2.php', ['limit' => 2], '<?limit=2&page=11>; rel="next"'],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetPaginationLink
+ *
+ * @param int $page
+ * @param string $scriptName
+ * @param array $params
+ * @param array $expected
+ */
+ public function testGetPaginationLink($page, $scriptName, $params, $expected) {
+ $this->request->expects($this->once())
+ ->method('getScriptName')
+ ->willReturn($scriptName);
+
+ $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'getPaginationLink', [$page, $params]));
+ }
+
+ public function dataIsV2() {
+ return [
+ ['/ocs/v1.php', false],
+ ['/ocs/v2.php', true],
+ ];
+ }
+
+ /**
+ * @dataProvider dataIsV2
+ *
+ * @param string $scriptName
+ * @param bool $expected
+ */
+ public function testIsV2($scriptName, $expected) {
+ $this->request->expects($this->once())
+ ->method('getScriptName')
+ ->willReturn($scriptName);
+
+ $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'isV2'));
+ }
+}
diff --git a/apps/user_ldap/l10n/tr.js b/apps/user_ldap/l10n/tr.js
index 8a4e0cad033..944d39928d0 100644
--- a/apps/user_ldap/l10n/tr.js
+++ b/apps/user_ldap/l10n/tr.js
@@ -32,11 +32,20 @@ OC.L10N.register(
"Mappings cleared successfully!" : "Eşleştirmeler başarıyla temizlendi!",
"Error while clearing the mappings." : "Eşleşmeler temizlenirken hata.",
"Anonymous bind is not allowed. Please provide a User DN and Password." : "Anonim atamaya izin verilmiyor. Lütfen bir Kullanıcı DN ve Parola sağlayın.",
+ "LDAP Operations error. Anonymous bind might not be allowed." : "LDAP İşlem hatası. Anonim bağlamaya izin verilmiyor.",
+ "Saving failed. Please make sure the database is in Operation. Reload before continuing." : "Kaydetme başarısız oldu. Veritabanının işlemde olduğundan emin olun. Devam etmeden yeniden yükleyin.",
+ "Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?" : "Kipi değiştirmek otomatik LDAP sorgularını etkinleştirecektir. LDAP'ınızın boyutlarına göre bu bir süre alacaktır. Kipi yine de değiştirmek istiyor musunuz?",
"Mode switch" : "Kip değişimi",
"Select attributes" : "Nitelikleri seç",
+ "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Kullanıcı bulunamadı. Lütfen oturum açtığınız nitelikleri ve kullanıcı adını kontrol edin. Etkili filtre (komut satırı doğrulaması için kopyala-yapıştır için): <br/>",
+ "User found and settings verified." : "Kullanıcı bulundu ve ayarlar doğrulandı.",
"Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Ayarlar doğrulandı ancak tek kullanıcı bulundu. Sadece ilk kullanıcı oturum açabilecek. Lütfen daha dar bir filtre seçin.",
"An unspecified error occurred. Please check the settings and the log." : "Belirtilmeyen bir hata oluştu. Lütfen ayarları ve günlüğü denetleyin.",
"The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "Arama filtresi, eşleşmeyen parantez sayısı sebebiyle oluşabilen sözdizimi sorunlarından dolayı geçersiz. Lütfen gözden geçirin.",
+ "A connection error to LDAP / AD occurred, please check host, port and credentials." : "LDAP / AD için bir bağlantı hatası oluştu, lütfen istemci, port ve kimlik bilgilerini kontrol edin.",
+ "The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD." : "%uid yer tutucusu eksik. LDAP / AD sorgularında kullanıcı adı ile değiştirilecek.",
+ "Please provide a login name to test against" : "Lütfen deneme için kullanılacak bir kullanıcı adı girin",
+ "The group box was disabled, because the LDAP / AD server does not support memberOf." : "LDAP / AD sunucusu memberOf desteklemediğinden grup kutusu kapatıldı.",
"_%s group found_::_%s groups found_" : ["%s grup bulundu","%s grup bulundu"],
"_%s user found_::_%s users found_" : ["%s kullanıcı bulundu","%s kullanıcı bulundu"],
"Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Görüntülenecek kullanıcı adı özelliği algılanamadı. Lütfen gelişmiş ldap ayarlarına girerek kendiniz belirleyin.",
@@ -60,6 +69,9 @@ OC.L10N.register(
"Verify settings and count groups" : "Ayarları doğrula ve grupları say",
"When logging in, %s will find the user based on the following attributes:" : "Oturum açılırken, %s, aşağıdaki özniteliklere bağlı kullanıcıyı bulacak:",
"LDAP / AD Username:" : "LDAP / AD Kullanıcı Adı:",
+ "Allows login against the LDAP / AD username, which is either uid or samaccountname and will be detected." : "LDAP / AD kullanıcı adı ile oturum açmaya izin verir.",
+ "LDAP / AD Email Address:" : "LDAP / AD Eposta Adresi:",
+ "Allows login against an email attribute. Mail and mailPrimaryAddress will be allowed." : "Bir eposta kimliği ile oturum açmaya izin verir. Mail ve mailPrimaryAddress'e izin verilir.",
"Other Attributes:" : "Diğer Nitelikler:",
"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Oturum açma girişimi olduğunda uygulanacak filtreyi tanımlar. %%uid, oturum işleminde kullanıcı adı ile değiştirilir. Örneğin: \"uid=%%uid\"",
"Test Loginname" : "Oturum açma adını sına",
diff --git a/apps/user_ldap/l10n/tr.json b/apps/user_ldap/l10n/tr.json
index f3641a9a16d..553dfe6cdbd 100644
--- a/apps/user_ldap/l10n/tr.json
+++ b/apps/user_ldap/l10n/tr.json
@@ -30,11 +30,20 @@
"Mappings cleared successfully!" : "Eşleştirmeler başarıyla temizlendi!",
"Error while clearing the mappings." : "Eşleşmeler temizlenirken hata.",
"Anonymous bind is not allowed. Please provide a User DN and Password." : "Anonim atamaya izin verilmiyor. Lütfen bir Kullanıcı DN ve Parola sağlayın.",
+ "LDAP Operations error. Anonymous bind might not be allowed." : "LDAP İşlem hatası. Anonim bağlamaya izin verilmiyor.",
+ "Saving failed. Please make sure the database is in Operation. Reload before continuing." : "Kaydetme başarısız oldu. Veritabanının işlemde olduğundan emin olun. Devam etmeden yeniden yükleyin.",
+ "Switching the mode will enable automatic LDAP queries. Depending on your LDAP size they may take a while. Do you still want to switch the mode?" : "Kipi değiştirmek otomatik LDAP sorgularını etkinleştirecektir. LDAP'ınızın boyutlarına göre bu bir süre alacaktır. Kipi yine de değiştirmek istiyor musunuz?",
"Mode switch" : "Kip değişimi",
"Select attributes" : "Nitelikleri seç",
+ "User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Kullanıcı bulunamadı. Lütfen oturum açtığınız nitelikleri ve kullanıcı adını kontrol edin. Etkili filtre (komut satırı doğrulaması için kopyala-yapıştır için): <br/>",
+ "User found and settings verified." : "Kullanıcı bulundu ve ayarlar doğrulandı.",
"Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Ayarlar doğrulandı ancak tek kullanıcı bulundu. Sadece ilk kullanıcı oturum açabilecek. Lütfen daha dar bir filtre seçin.",
"An unspecified error occurred. Please check the settings and the log." : "Belirtilmeyen bir hata oluştu. Lütfen ayarları ve günlüğü denetleyin.",
"The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "Arama filtresi, eşleşmeyen parantez sayısı sebebiyle oluşabilen sözdizimi sorunlarından dolayı geçersiz. Lütfen gözden geçirin.",
+ "A connection error to LDAP / AD occurred, please check host, port and credentials." : "LDAP / AD için bir bağlantı hatası oluştu, lütfen istemci, port ve kimlik bilgilerini kontrol edin.",
+ "The %uid placeholder is missing. It will be replaced with the login name when querying LDAP / AD." : "%uid yer tutucusu eksik. LDAP / AD sorgularında kullanıcı adı ile değiştirilecek.",
+ "Please provide a login name to test against" : "Lütfen deneme için kullanılacak bir kullanıcı adı girin",
+ "The group box was disabled, because the LDAP / AD server does not support memberOf." : "LDAP / AD sunucusu memberOf desteklemediğinden grup kutusu kapatıldı.",
"_%s group found_::_%s groups found_" : ["%s grup bulundu","%s grup bulundu"],
"_%s user found_::_%s users found_" : ["%s kullanıcı bulundu","%s kullanıcı bulundu"],
"Could not detect user display name attribute. Please specify it yourself in advanced ldap settings." : "Görüntülenecek kullanıcı adı özelliği algılanamadı. Lütfen gelişmiş ldap ayarlarına girerek kendiniz belirleyin.",
@@ -58,6 +67,9 @@
"Verify settings and count groups" : "Ayarları doğrula ve grupları say",
"When logging in, %s will find the user based on the following attributes:" : "Oturum açılırken, %s, aşağıdaki özniteliklere bağlı kullanıcıyı bulacak:",
"LDAP / AD Username:" : "LDAP / AD Kullanıcı Adı:",
+ "Allows login against the LDAP / AD username, which is either uid or samaccountname and will be detected." : "LDAP / AD kullanıcı adı ile oturum açmaya izin verir.",
+ "LDAP / AD Email Address:" : "LDAP / AD Eposta Adresi:",
+ "Allows login against an email attribute. Mail and mailPrimaryAddress will be allowed." : "Bir eposta kimliği ile oturum açmaya izin verir. Mail ve mailPrimaryAddress'e izin verilir.",
"Other Attributes:" : "Diğer Nitelikler:",
"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" : "Oturum açma girişimi olduğunda uygulanacak filtreyi tanımlar. %%uid, oturum işleminde kullanıcı adı ile değiştirilir. Örneğin: \"uid=%%uid\"",
"Test Loginname" : "Oturum açma adını sına",
diff --git a/autotest-external.sh b/autotest-external.sh
index 65d53aaa95d..cb5a3dad503 100755
--- a/autotest-external.sh
+++ b/autotest-external.sh
@@ -17,6 +17,9 @@ BASEDIR=$PWD
DBCONFIGS="sqlite mysql pgsql oci"
PHPUNIT=$(which phpunit)
+_XDEBUG_CONFIG=$XDEBUG_CONFIG
+unset XDEBUG_CONFIG
+
function print_syntax {
echo -e "Syntax: ./autotest-external.sh [dbconfigname] [startfile]\n" >&2
echo -e "\t\"dbconfigname\" can be one of: $DBCONFIGS" >&2
@@ -159,6 +162,9 @@ EOF
mkdir "coverage-external-html-$1"
# just enable files_external
php ../occ app:enable files_external
+ if [[ "$_XDEBUG_CONFIG" ]]; then
+ export XDEBUG_CONFIG=$_XDEBUG_CONFIG
+ fi
if [ -z "$NOCOVERAGE" ]; then
"$PHPUNIT" --configuration phpunit-autotest-external.xml --log-junit "autotest-external-results-$1.xml" --coverage-clover "autotest-external-clover-$1.xml" --coverage-html "coverage-external-html-$1"
RESULT=$?
diff --git a/autotest.sh b/autotest.sh
index 0e112bfda32..6a09fbfabac 100755
--- a/autotest.sh
+++ b/autotest.sh
@@ -32,6 +32,9 @@ fi
PHP=$(which "$PHP_EXE")
PHPUNIT=$(which phpunit)
+_XDEBUG_CONFIG=$XDEBUG_CONFIG
+unset XDEBUG_CONFIG
+
function print_syntax {
echo -e "Syntax: ./autotest.sh [dbconfigname] [testfile]\n" >&2
echo -e "\t\"dbconfigname\" can be one of: $DBCONFIGS" >&2
@@ -217,6 +220,9 @@ function execute_tests {
rm -rf "coverage-html-$DB"
mkdir "coverage-html-$DB"
"$PHP" -f enable_all.php | grep -i -C9999 error && echo "Error during setup" && exit 101
+ if [[ "$_XDEBUG_CONFIG" ]]; then
+ export XDEBUG_CONFIG=$_XDEBUG_CONFIG
+ fi
if [ -z "$NOCOVERAGE" ]; then
"${PHPUNIT[@]}" --configuration phpunit-autotest.xml --log-junit "autotest-results-$DB.xml" --coverage-clover "autotest-clover-$DB.xml" --coverage-html "coverage-html-$DB" "$2" "$3"
RESULT=$?
diff --git a/core/ajax/preview.php b/core/ajax/preview.php
index fc98d80eb0e..baa0ed4ec61 100644
--- a/core/ajax/preview.php
+++ b/core/ajax/preview.php
@@ -31,6 +31,7 @@ $maxY = array_key_exists('y', $_GET) ? (int)$_GET['y'] : '36';
$scalingUp = array_key_exists('scalingup', $_GET) ? (bool)$_GET['scalingup'] : true;
$keepAspect = array_key_exists('a', $_GET) ? true : false;
$always = array_key_exists('forceIcon', $_GET) ? (bool)$_GET['forceIcon'] : true;
+$mode = array_key_exists('mode', $_GET) ? $_GET['mode'] : 'fill';
if ($file === '') {
//400 Bad Request
@@ -56,6 +57,7 @@ if (!$info instanceof OCP\Files\FileInfo || !$always && !\OC::$server->getPrevie
$preview->setMaxX($maxX);
$preview->setMaxY($maxY);
$preview->setScalingUp($scalingUp);
+ $preview->setMode($mode);
$preview->setKeepAspect($keepAspect);
$preview->showPreview();
}
diff --git a/core/command/encryption/changekeystorageroot.php b/core/command/encryption/changekeystorageroot.php
new file mode 100644
index 00000000000..662e0a3161a
--- /dev/null
+++ b/core/command/encryption/changekeystorageroot.php
@@ -0,0 +1,270 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OC\Core\Command\Encryption;
+
+use OC\Encryption\Keys\Storage;
+use OC\Encryption\Util;
+use OC\Files\Filesystem;
+use OC\Files\View;
+use OCP\IConfig;
+use OCP\IUserManager;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\ConfirmationQuestion;
+
+class ChangeKeyStorageRoot extends Command {
+
+ /** @var View */
+ protected $rootView;
+
+ /** @var IUserManager */
+ protected $userManager;
+
+ /** @var IConfig */
+ protected $config;
+
+ /** @var Util */
+ protected $util;
+
+ /** @var QuestionHelper */
+ protected $questionHelper;
+
+ /**
+ * @param View $view
+ * @param IUserManager $userManager
+ * @param IConfig $config
+ * @param Util $util
+ * @param QuestionHelper $questionHelper
+ */
+ public function __construct(View $view, IUserManager $userManager, IConfig $config, Util $util, QuestionHelper $questionHelper) {
+ parent::__construct();
+ $this->rootView = $view;
+ $this->userManager = $userManager;
+ $this->config = $config;
+ $this->util = $util;
+ $this->questionHelper = $questionHelper;
+ }
+
+ protected function configure() {
+ parent::configure();
+ $this
+ ->setName('encryption:change-key-storage-root')
+ ->setDescription('Change key storage root')
+ ->addArgument(
+ 'newRoot',
+ InputArgument::OPTIONAL,
+ 'new root of the key storage relative to the data folder'
+ );
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ $oldRoot = $this->util->getKeyStorageRoot();
+ $newRoot = $input->getArgument('newRoot');
+
+ if ($newRoot === null) {
+ $question = new ConfirmationQuestion('No storage root given, do you want to reset the key storage root to the default location? (y/n) ', false);
+ if (!$this->questionHelper->ask($input, $output, $question)) {
+ return;
+ }
+ $newRoot = '';
+ }
+
+ $oldRootDescription = $oldRoot !== '' ? $oldRoot : 'default storage location';
+ $newRootDescription = $newRoot !== '' ? $newRoot : 'default storage location';
+ $output->writeln("Change key storage root from <info>$oldRootDescription</info> to <info>$newRootDescription</info>");
+ $success = $this->moveAllKeys($oldRoot, $newRoot, $output);
+ if ($success) {
+ $this->util->setKeyStorageRoot($newRoot);
+ $output->writeln('');
+ $output->writeln("Key storage root successfully changed to <info>$newRootDescription</info>");
+ }
+ }
+
+ /**
+ * move keys to new key storage root
+ *
+ * @param string $oldRoot
+ * @param string $newRoot
+ * @param OutputInterface $output
+ * @return bool
+ * @throws \Exception
+ */
+ protected function moveAllKeys($oldRoot, $newRoot, OutputInterface $output) {
+
+ $output->writeln("Start to move keys:");
+
+ if ($this->rootView->is_dir(($oldRoot)) === false) {
+ $output->writeln("No old keys found: Nothing needs to be moved");
+ return false;
+ }
+
+ $this->prepareNewRoot($newRoot);
+ $this->moveSystemKeys($oldRoot, $newRoot);
+ $this->moveUserKeys($oldRoot, $newRoot, $output);
+
+ return true;
+ }
+
+ /**
+ * prepare new key storage
+ *
+ * @param string $newRoot
+ * @throws \Exception
+ */
+ protected function prepareNewRoot($newRoot) {
+ if ($this->rootView->is_dir($newRoot) === false) {
+ throw new \Exception("New root folder doesn't exist. Please create the folder or check the permissions and try again.");
+ }
+
+ $result = $this->rootView->file_put_contents(
+ $newRoot . '/' . Storage::KEY_STORAGE_MARKER,
+ 'ownCloud will detect this folder as key storage root only if this file exists'
+ );
+
+ if ($result === false) {
+ throw new \Exception("Can't write to new root folder. Please check the permissions and try again");
+ }
+
+ }
+
+
+ /**
+ * move system key folder
+ *
+ * @param string $oldRoot
+ * @param string $newRoot
+ */
+ protected function moveSystemKeys($oldRoot, $newRoot) {
+ if (
+ $this->rootView->is_dir($oldRoot . '/files_encryption') &&
+ $this->targetExists($newRoot . '/files_encryption') === false
+ ) {
+ $this->rootView->rename($oldRoot . '/files_encryption', $newRoot . '/files_encryption');
+ }
+ }
+
+
+ /**
+ * setup file system for the given user
+ *
+ * @param string $uid
+ */
+ protected function setupUserFS($uid) {
+ \OC_Util::tearDownFS();
+ \OC_Util::setupFS($uid);
+ }
+
+
+ /**
+ * iterate over each user and move the keys to the new storage
+ *
+ * @param string $oldRoot
+ * @param string $newRoot
+ * @param OutputInterface $output
+ */
+ protected function moveUserKeys($oldRoot, $newRoot, OutputInterface $output) {
+
+ $progress = new ProgressBar($output);
+ $progress->start();
+
+
+ foreach($this->userManager->getBackends() as $backend) {
+ $limit = 500;
+ $offset = 0;
+ do {
+ $users = $backend->getUsers('', $limit, $offset);
+ foreach ($users as $user) {
+ $progress->advance();
+ $this->setupUserFS($user);
+ $this->moveUserEncryptionFolder($user, $oldRoot, $newRoot);
+ }
+ $offset += $limit;
+ } while(count($users) >= $limit);
+ }
+ $progress->finish();
+ }
+
+ /**
+ * move user encryption folder to new root folder
+ *
+ * @param string $user
+ * @param string $oldRoot
+ * @param string $newRoot
+ * @throws \Exception
+ */
+ protected function moveUserEncryptionFolder($user, $oldRoot, $newRoot) {
+
+ if ($this->userManager->userExists($user)) {
+
+ $source = $oldRoot . '/' . $user . '/files_encryption';
+ $target = $newRoot . '/' . $user . '/files_encryption';
+ if (
+ $this->rootView->is_dir($source) &&
+ $this->targetExists($target) === false
+ ) {
+ $this->prepareParentFolder($newRoot . '/' . $user);
+ $this->rootView->rename($source, $target);
+ }
+ }
+ }
+
+ /**
+ * Make preparations to filesystem for saving a key file
+ *
+ * @param string $path relative to data/
+ */
+ protected function prepareParentFolder($path) {
+ $path = Filesystem::normalizePath($path);
+ // If the file resides within a subdirectory, create it
+ if ($this->rootView->file_exists($path) === false) {
+ $sub_dirs = explode('/', ltrim($path, '/'));
+ $dir = '';
+ foreach ($sub_dirs as $sub_dir) {
+ $dir .= '/' . $sub_dir;
+ if ($this->rootView->file_exists($dir) === false) {
+ $this->rootView->mkdir($dir);
+ }
+ }
+ }
+ }
+
+ /**
+ * check if target already exists
+ *
+ * @param $path
+ * @return bool
+ * @throws \Exception
+ */
+ protected function targetExists($path) {
+ if ($this->rootView->file_exists($path)) {
+ throw new \Exception("new folder '$path' already exists");
+ }
+
+ return false;
+ }
+
+}
diff --git a/core/command/encryption/showkeystorageroot.php b/core/command/encryption/showkeystorageroot.php
new file mode 100644
index 00000000000..acb2e75a6ae
--- /dev/null
+++ b/core/command/encryption/showkeystorageroot.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OC\Core\Command\Encryption;
+
+use OC\Encryption\Util;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ShowKeyStorageRoot extends Command{
+
+ /** @var Util */
+ protected $util;
+
+ /**
+ * @param Util $util
+ */
+ public function __construct(Util $util) {
+ parent::__construct();
+ $this->util = $util;
+ }
+
+ protected function configure() {
+ parent::configure();
+ $this
+ ->setName('encryption:show-key-storage-root')
+ ->setDescription('Show current key storage root');
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ $currentRoot = $this->util->getKeyStorageRoot();
+
+ $rootDescription = $currentRoot !== '' ? $currentRoot : 'default storage location (data/)';
+
+ $output->writeln("Current key storage root: <info>$rootDescription</info>");
+ }
+
+}
diff --git a/core/css/apps.css b/core/css/apps.css
index 846eba8e4bf..4118e6ea668 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -28,6 +28,7 @@
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
+ border-right: 1px solid #eee;
}
#app-navigation > ul {
position: relative;
@@ -482,6 +483,10 @@
max-height: 300px;
overflow-y: auto;
}
+#app-settings-content,
+#app-settings-header {
+ border-right: 1px solid #eee;
+}
/* display input fields at full width */
#app-settings-content input[type='text'] {
diff --git a/core/js/tests/specs/appsSpec.js b/core/js/tests/specs/appsSpec.js
new file mode 100644
index 00000000000..536d41c7f10
--- /dev/null
+++ b/core/js/tests/specs/appsSpec.js
@@ -0,0 +1,48 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2015 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+describe('Apps base tests', function() {
+ describe('Sidebar utility functions', function() {
+ beforeEach(function() {
+ $('#testArea').append('<div id="app-content">Content</div><div id="app-sidebar">The sidebar</div>');
+ });
+ it('shows sidebar', function() {
+ var $el = $('#app-sidebar');
+ OC.Apps.showAppSidebar();
+ expect($el.hasClass('disappear')).toEqual(false);
+ });
+ it('hides sidebar', function() {
+ var $el = $('#app-sidebar');
+ OC.Apps.showAppSidebar();
+ OC.Apps.hideAppSidebar();
+ expect($el.hasClass('disappear')).toEqual(true);
+ });
+ it('triggers appresize event when visibility changed', function() {
+ var eventStub = sinon.stub();
+ $('#app-content').on('appresized', eventStub);
+ OC.Apps.showAppSidebar();
+ expect(eventStub.calledOnce).toEqual(true);
+ OC.Apps.hideAppSidebar();
+ expect(eventStub.calledTwice).toEqual(true);
+ });
+ });
+});
+
diff --git a/core/l10n/fr.js b/core/l10n/fr.js
index 8b0fbdbe836..2ed3872dffb 100644
--- a/core/l10n/fr.js
+++ b/core/l10n/fr.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"core",
{
"Couldn't send mail to following users: %s " : "Impossible d'envoyer un courriel aux utilisateurs suivants : %s",
+ "Preparing update" : "Préparation de la mise à jour",
"Turned on maintenance mode" : "Mode de maintenance activé",
"Turned off maintenance mode" : "Mode de maintenance désactivé",
"Maintenance mode is kept active" : "Le mode de maintenance est laissé actif",
@@ -172,6 +173,7 @@ OC.L10N.register(
"The update was successful. There were warnings." : "La mise à jour a réussi, mais il y a eu des avertissements",
"The update was successful. Redirecting you to ownCloud now." : "La mise à jour a réussi. Vous êtes maintenant redirigé vers ownCloud.",
"Couldn't reset password because the token is invalid" : "Impossible de réinitialiser le mot de passe car le jeton n'est pas valable.",
+ "Couldn't reset password because the token is expired" : "Impossible de réinitialiser le mot de passe car le jeton a expiré.",
"Couldn't send reset email. Please make sure your username is correct." : "Impossible d'envoyer le courriel de réinitialisation. Veuillez vérifier que votre nom d'utilisateur est correct.",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "Impossible d'envoyer le courriel de réinitialisation car il n'y a aucune adresse de courriel pour cet utilisateur. Veuillez contacter votre administrateur.",
"%s password reset" : "Réinitialisation de votre mot de passe %s",
diff --git a/core/l10n/fr.json b/core/l10n/fr.json
index 2eb2a722298..761132e4bde 100644
--- a/core/l10n/fr.json
+++ b/core/l10n/fr.json
@@ -1,5 +1,6 @@
{ "translations": {
"Couldn't send mail to following users: %s " : "Impossible d'envoyer un courriel aux utilisateurs suivants : %s",
+ "Preparing update" : "Préparation de la mise à jour",
"Turned on maintenance mode" : "Mode de maintenance activé",
"Turned off maintenance mode" : "Mode de maintenance désactivé",
"Maintenance mode is kept active" : "Le mode de maintenance est laissé actif",
@@ -170,6 +171,7 @@
"The update was successful. There were warnings." : "La mise à jour a réussi, mais il y a eu des avertissements",
"The update was successful. Redirecting you to ownCloud now." : "La mise à jour a réussi. Vous êtes maintenant redirigé vers ownCloud.",
"Couldn't reset password because the token is invalid" : "Impossible de réinitialiser le mot de passe car le jeton n'est pas valable.",
+ "Couldn't reset password because the token is expired" : "Impossible de réinitialiser le mot de passe car le jeton a expiré.",
"Couldn't send reset email. Please make sure your username is correct." : "Impossible d'envoyer le courriel de réinitialisation. Veuillez vérifier que votre nom d'utilisateur est correct.",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "Impossible d'envoyer le courriel de réinitialisation car il n'y a aucune adresse de courriel pour cet utilisateur. Veuillez contacter votre administrateur.",
"%s password reset" : "Réinitialisation de votre mot de passe %s",
diff --git a/core/l10n/hu_HU.js b/core/l10n/hu_HU.js
index ff04fe9900c..b465daa4212 100644
--- a/core/l10n/hu_HU.js
+++ b/core/l10n/hu_HU.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"core",
{
"Couldn't send mail to following users: %s " : "Nem sikerült e-mailt küldeni a következő felhasználóknak: %s",
+ "Preparing update" : "Felkészülés a frissítésre",
"Turned on maintenance mode" : "A karbantartási mód bekapcsolva",
"Turned off maintenance mode" : "A karbantartási mód kikapcsolva",
"Maintenance mode is kept active" : "Karbantartási mód aktiválva marad",
@@ -13,6 +14,7 @@ OC.L10N.register(
"Repair error: " : "Javítás hiba:",
"Following incompatible apps have been disabled: %s" : "A következő nem kompatibilis applikációk lettek tiltva: %s",
"Following apps have been disabled: %s" : "A következő applikációk lettek tiltva: %s",
+ "Already up to date" : "Már a legfrissebb változat",
"File is too big" : "A fájl túl nagy",
"Invalid file provided" : "Érvénytelen fájl van megadva",
"No image or file provided" : "Nincs kép vagy fájl megadva",
diff --git a/core/l10n/hu_HU.json b/core/l10n/hu_HU.json
index d7c20ae181b..e8b3e20c33e 100644
--- a/core/l10n/hu_HU.json
+++ b/core/l10n/hu_HU.json
@@ -1,5 +1,6 @@
{ "translations": {
"Couldn't send mail to following users: %s " : "Nem sikerült e-mailt küldeni a következő felhasználóknak: %s",
+ "Preparing update" : "Felkészülés a frissítésre",
"Turned on maintenance mode" : "A karbantartási mód bekapcsolva",
"Turned off maintenance mode" : "A karbantartási mód kikapcsolva",
"Maintenance mode is kept active" : "Karbantartási mód aktiválva marad",
@@ -11,6 +12,7 @@
"Repair error: " : "Javítás hiba:",
"Following incompatible apps have been disabled: %s" : "A következő nem kompatibilis applikációk lettek tiltva: %s",
"Following apps have been disabled: %s" : "A következő applikációk lettek tiltva: %s",
+ "Already up to date" : "Már a legfrissebb változat",
"File is too big" : "A fájl túl nagy",
"Invalid file provided" : "Érvénytelen fájl van megadva",
"No image or file provided" : "Nincs kép vagy fájl megadva",
diff --git a/core/l10n/id.js b/core/l10n/id.js
index 9af2d3bad0c..0540b9ae0bd 100644
--- a/core/l10n/id.js
+++ b/core/l10n/id.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"core",
{
"Couldn't send mail to following users: %s " : "Tidak dapat mengirim Email ke pengguna berikut: %s",
+ "Preparing update" : "Mempersiapkan pembaruan",
"Turned on maintenance mode" : "Hidupkan mode perawatan",
"Turned off maintenance mode" : "Matikan mode perawatan",
"Maintenance mode is kept active" : "Mode Pemeliharaan masih aktif",
@@ -13,6 +14,7 @@ OC.L10N.register(
"Repair error: " : "Kesalahan perbaikan:",
"Following incompatible apps have been disabled: %s" : "Aplikasi tidak kompatibel berikut telah dinonaktifkan: %s",
"Following apps have been disabled: %s" : "Aplikasi berikut telah dinonaktifkan: %s",
+ "Already up to date" : "Sudah yang terbaru",
"File is too big" : "Berkas terlalu besar",
"Invalid file provided" : "Berkas yang diberikan tidak sah",
"No image or file provided" : "Tidak ada gambar atau berkas yang disediakan",
@@ -172,6 +174,7 @@ OC.L10N.register(
"The update was successful. There were warnings." : "Pembaruan telah berhasil. Terdapat peringatan.",
"The update was successful. Redirecting you to ownCloud now." : "Pembaruan sukses. Anda akan diarahkan ulang ke ownCloud.",
"Couldn't reset password because the token is invalid" : "Tidak dapat menyetel ulang sandi karena token tidak sah",
+ "Couldn't reset password because the token is expired" : "Tidak dapat menyetel ulang sandi karena token telah kadaluarsa",
"Couldn't send reset email. Please make sure your username is correct." : "Tidak dapat menyetel ulang email. Mohon pastikan nama pengguna Anda benar.",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "Tidak dapat menyetel ulang email karena tidak ada alamat email untuk nama pengguna ini. Silakan hubungi Administrator Anda.",
"%s password reset" : "%s sandi disetel ulang",
diff --git a/core/l10n/id.json b/core/l10n/id.json
index 79a84db45c5..d03ae4ae4ec 100644
--- a/core/l10n/id.json
+++ b/core/l10n/id.json
@@ -1,5 +1,6 @@
{ "translations": {
"Couldn't send mail to following users: %s " : "Tidak dapat mengirim Email ke pengguna berikut: %s",
+ "Preparing update" : "Mempersiapkan pembaruan",
"Turned on maintenance mode" : "Hidupkan mode perawatan",
"Turned off maintenance mode" : "Matikan mode perawatan",
"Maintenance mode is kept active" : "Mode Pemeliharaan masih aktif",
@@ -11,6 +12,7 @@
"Repair error: " : "Kesalahan perbaikan:",
"Following incompatible apps have been disabled: %s" : "Aplikasi tidak kompatibel berikut telah dinonaktifkan: %s",
"Following apps have been disabled: %s" : "Aplikasi berikut telah dinonaktifkan: %s",
+ "Already up to date" : "Sudah yang terbaru",
"File is too big" : "Berkas terlalu besar",
"Invalid file provided" : "Berkas yang diberikan tidak sah",
"No image or file provided" : "Tidak ada gambar atau berkas yang disediakan",
@@ -170,6 +172,7 @@
"The update was successful. There were warnings." : "Pembaruan telah berhasil. Terdapat peringatan.",
"The update was successful. Redirecting you to ownCloud now." : "Pembaruan sukses. Anda akan diarahkan ulang ke ownCloud.",
"Couldn't reset password because the token is invalid" : "Tidak dapat menyetel ulang sandi karena token tidak sah",
+ "Couldn't reset password because the token is expired" : "Tidak dapat menyetel ulang sandi karena token telah kadaluarsa",
"Couldn't send reset email. Please make sure your username is correct." : "Tidak dapat menyetel ulang email. Mohon pastikan nama pengguna Anda benar.",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "Tidak dapat menyetel ulang email karena tidak ada alamat email untuk nama pengguna ini. Silakan hubungi Administrator Anda.",
"%s password reset" : "%s sandi disetel ulang",
diff --git a/core/l10n/tr.js b/core/l10n/tr.js
index bedc5ce7e26..2b319a8f8fe 100644
--- a/core/l10n/tr.js
+++ b/core/l10n/tr.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"core",
{
"Couldn't send mail to following users: %s " : "Şu kullanıcılara posta gönderilemedi: %s",
+ "Preparing update" : "Güncelleme hazırlanıyor",
"Turned on maintenance mode" : "Bakım kipi etkinleştirildi",
"Turned off maintenance mode" : "Bakım kipi kapatıldı",
"Maintenance mode is kept active" : "Bakım kipi etkin tutuldu",
@@ -13,6 +14,8 @@ OC.L10N.register(
"Repair error: " : "Onarım hatası:",
"Following incompatible apps have been disabled: %s" : "Aşağıdaki uyumsuz uygulamalar devre dışı bırakıldı: %s",
"Following apps have been disabled: %s" : "Aşağıdaki uygulamalar devre dışı bırakıldı: %s",
+ "Already up to date" : "Zaten güncel",
+ "File is too big" : "Dosya çok büyük",
"Invalid file provided" : "Geçersiz dosya sağlandı",
"No image or file provided" : "Resim veya dosya belirtilmedi",
"Unknown filetype" : "Bilinmeyen dosya türü",
@@ -35,6 +38,13 @@ OC.L10N.register(
"Thu." : "Per.",
"Fri." : "Cum.",
"Sat." : "Cmt.",
+ "Su" : "Pa",
+ "Mo" : "Pt",
+ "Tu" : "Sa",
+ "We" : "Ça",
+ "Th" : "Pe",
+ "Fr" : "Cu",
+ "Sa" : "Ct",
"January" : "Ocak",
"February" : "Şubat",
"March" : "Mart",
@@ -94,6 +104,8 @@ OC.L10N.register(
"Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "data dizininiz ve dosyalarınız büyük ihtimalle İnternet üzerinden erişilebilir. .htaccess dosyası çalışmıyor. Web sunucunuzu yapılandırarak data dizinine erişimi kapatmanızı veya data dizinini web sunucu belge dizini dışına almanızı şiddetle tavsiye ederiz.",
"No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Hafıza önbelleği ayarlanmamış. Performansın artması için mümkünse lütfen bir memcache ayarlayın. Detaylı bilgiye <a href=\"{docLink}\">belgelendirmemizden</a> ulaşabilirsiniz.",
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Güvenlik sebepleri ile şiddetle kaçınılması gereken /dev/urandom PHP tarafından okunamıyor. Daha fazla bilgi <a href=\"{docLink}\">belgelendirmemizde</a> bulunabilir.",
+ "Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "Kullandığınız PHP sürümü ({version}) artık <a href=\"{phpLink}\">PHP tarafından desteklenmiyor</a>. PHP tarafından sağlanan performans ve güvenlik güncellemelerinden faydalanmak için PHP sürümünüzü güncellemenizi öneririz.",
+ "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Ters vekil sunucu başlık yapılandırması hatalı veya ownCloud'a güvenilen bir vekil sunucusundan erişiyorsunuz. ownCloud'a güvenilen bir vekil sunucusundan erişmiyorsanız bu bir güvenlik problemidir ve bir saldırganın IP adresinizi taklit etmesine izin verebilir. Ayrıntılı bilgiyi <a href=\"{docLink}\">belgelendirmemizde</a> bulabilirsiniz.",
"Error occurred while checking server setup" : "Sunucu yapılandırması denetlenirken hata oluştu",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı \"{expected}\" ile eşleşmek üzere yapılandırılmamış. Bu muhtemel bir güvenlik veya gizlilik riski olduğundan bu ayarı düzeltmenizi öneririz.",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "\"Strict-Transport-Security\" HTTP başlığı en az \"{seconds}\" saniye olarak ayarlanmış. İyileştirilmiş güvenlik için <a href=\"{docUrl}\">güvenlik ipuçlarımızda</a> belirtilen HSTS etkinleştirmesini öneririz.",
@@ -162,6 +174,7 @@ OC.L10N.register(
"The update was successful. There were warnings." : "Güncelleme başarılı. Uyarılar mevcut.",
"The update was successful. Redirecting you to ownCloud now." : "Güncelleme başarılı. Şimdi ownCloud'a yönlendiriliyorsunuz.",
"Couldn't reset password because the token is invalid" : "Belirteç geçersiz olduğundan parola sıfırlanamadı",
+ "Couldn't reset password because the token is expired" : "Jeton zaman aşımına uğradığından parola sıfırlanamadı",
"Couldn't send reset email. Please make sure your username is correct." : "Sıfırlama e-postası gönderilemedi. Lütfen kullanıcı adınızın doğru olduğundan emin olun.",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "Sıfırlama e-postası, bu kullanıcı için bir e-posta adresi olmadığından gönderilemedi. Lütfen yöneticiniz ile iletişime geçin.",
"%s password reset" : "%s parola sıfırlama",
@@ -235,6 +248,7 @@ OC.L10N.register(
"Please contact your administrator." : "Lütfen sistem yöneticiniz ile iletişime geçin.",
"An internal error occured." : "Dahili bir hata oluştu.",
"Please try again or contact your administrator." : "Lütfen yeniden deneyin veya yöneticinizle iletişim kurun.",
+ "Wrong password. Reset it?" : "Hatalı parola. Sıfırlansın mı?",
"remember" : "hatırla",
"Alternative Logins" : "Alternatif Girişler",
"Hey there,<br><br>just letting you know that %s shared <strong>%s</strong> with you.<br><a href=\"%s\">View it!</a><br><br>" : "Merhaba, <br><br>%s kullanıcısının sizinle <strong>%s</strong> paylaşımında bulunduğunu bildirmek istedik.<br><a href=\"%s\">Paylaşımı gör!</a><br><br>",
@@ -246,6 +260,10 @@ OC.L10N.register(
"Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Lütfen yöneticiniz ile iletişime geçin. Eğer bu örneğin bir yöneticisi iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını yapılandırın. Bu yapılandırmanın bir örneği config/config.sample.php dosyasında verilmiştir.",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Yapılandırmanıza bağlı olarak, bir yönetici olarak bu alan adına güvenmek için aşağıdaki düğmeyi de kullanabilirsiniz.",
"Add \"%s\" as trusted domain" : "\"%s\" alan adını güvenilir olarak ekle",
+ "App update required" : "Uygulama güncellemesi gerekli",
+ "%s will be updated to version %s" : "%s, %s sürümüne güncellenecek",
+ "These apps will be updated:" : "Bu uygulamalar güncellenecek:",
+ "These incompatible apps will be disabled:" : "Bu uyumsuz uygulamalar kapatılacaklar:",
"The theme %s has been disabled." : "%s teması devre dışı bırakıldı.",
"Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Devam etmeden önce lütfen veritabanının, yapılandırma ve veri klasörlerinin yedeklenmiş olduğundan emin olun.",
"Start update" : "Güncellemeyi başlat",
diff --git a/core/l10n/tr.json b/core/l10n/tr.json
index 3925a97627d..26f831b9262 100644
--- a/core/l10n/tr.json
+++ b/core/l10n/tr.json
@@ -1,5 +1,6 @@
{ "translations": {
"Couldn't send mail to following users: %s " : "Şu kullanıcılara posta gönderilemedi: %s",
+ "Preparing update" : "Güncelleme hazırlanıyor",
"Turned on maintenance mode" : "Bakım kipi etkinleştirildi",
"Turned off maintenance mode" : "Bakım kipi kapatıldı",
"Maintenance mode is kept active" : "Bakım kipi etkin tutuldu",
@@ -11,6 +12,8 @@
"Repair error: " : "Onarım hatası:",
"Following incompatible apps have been disabled: %s" : "Aşağıdaki uyumsuz uygulamalar devre dışı bırakıldı: %s",
"Following apps have been disabled: %s" : "Aşağıdaki uygulamalar devre dışı bırakıldı: %s",
+ "Already up to date" : "Zaten güncel",
+ "File is too big" : "Dosya çok büyük",
"Invalid file provided" : "Geçersiz dosya sağlandı",
"No image or file provided" : "Resim veya dosya belirtilmedi",
"Unknown filetype" : "Bilinmeyen dosya türü",
@@ -33,6 +36,13 @@
"Thu." : "Per.",
"Fri." : "Cum.",
"Sat." : "Cmt.",
+ "Su" : "Pa",
+ "Mo" : "Pt",
+ "Tu" : "Sa",
+ "We" : "Ça",
+ "Th" : "Pe",
+ "Fr" : "Cu",
+ "Sa" : "Ct",
"January" : "Ocak",
"February" : "Şubat",
"March" : "Mart",
@@ -92,6 +102,8 @@
"Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "data dizininiz ve dosyalarınız büyük ihtimalle İnternet üzerinden erişilebilir. .htaccess dosyası çalışmıyor. Web sunucunuzu yapılandırarak data dizinine erişimi kapatmanızı veya data dizinini web sunucu belge dizini dışına almanızı şiddetle tavsiye ederiz.",
"No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Hafıza önbelleği ayarlanmamış. Performansın artması için mümkünse lütfen bir memcache ayarlayın. Detaylı bilgiye <a href=\"{docLink}\">belgelendirmemizden</a> ulaşabilirsiniz.",
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Güvenlik sebepleri ile şiddetle kaçınılması gereken /dev/urandom PHP tarafından okunamıyor. Daha fazla bilgi <a href=\"{docLink}\">belgelendirmemizde</a> bulunabilir.",
+ "Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "Kullandığınız PHP sürümü ({version}) artık <a href=\"{phpLink}\">PHP tarafından desteklenmiyor</a>. PHP tarafından sağlanan performans ve güvenlik güncellemelerinden faydalanmak için PHP sürümünüzü güncellemenizi öneririz.",
+ "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Ters vekil sunucu başlık yapılandırması hatalı veya ownCloud'a güvenilen bir vekil sunucusundan erişiyorsunuz. ownCloud'a güvenilen bir vekil sunucusundan erişmiyorsanız bu bir güvenlik problemidir ve bir saldırganın IP adresinizi taklit etmesine izin verebilir. Ayrıntılı bilgiyi <a href=\"{docLink}\">belgelendirmemizde</a> bulabilirsiniz.",
"Error occurred while checking server setup" : "Sunucu yapılandırması denetlenirken hata oluştu",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı \"{expected}\" ile eşleşmek üzere yapılandırılmamış. Bu muhtemel bir güvenlik veya gizlilik riski olduğundan bu ayarı düzeltmenizi öneririz.",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "\"Strict-Transport-Security\" HTTP başlığı en az \"{seconds}\" saniye olarak ayarlanmış. İyileştirilmiş güvenlik için <a href=\"{docUrl}\">güvenlik ipuçlarımızda</a> belirtilen HSTS etkinleştirmesini öneririz.",
@@ -160,6 +172,7 @@
"The update was successful. There were warnings." : "Güncelleme başarılı. Uyarılar mevcut.",
"The update was successful. Redirecting you to ownCloud now." : "Güncelleme başarılı. Şimdi ownCloud'a yönlendiriliyorsunuz.",
"Couldn't reset password because the token is invalid" : "Belirteç geçersiz olduğundan parola sıfırlanamadı",
+ "Couldn't reset password because the token is expired" : "Jeton zaman aşımına uğradığından parola sıfırlanamadı",
"Couldn't send reset email. Please make sure your username is correct." : "Sıfırlama e-postası gönderilemedi. Lütfen kullanıcı adınızın doğru olduğundan emin olun.",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "Sıfırlama e-postası, bu kullanıcı için bir e-posta adresi olmadığından gönderilemedi. Lütfen yöneticiniz ile iletişime geçin.",
"%s password reset" : "%s parola sıfırlama",
@@ -233,6 +246,7 @@
"Please contact your administrator." : "Lütfen sistem yöneticiniz ile iletişime geçin.",
"An internal error occured." : "Dahili bir hata oluştu.",
"Please try again or contact your administrator." : "Lütfen yeniden deneyin veya yöneticinizle iletişim kurun.",
+ "Wrong password. Reset it?" : "Hatalı parola. Sıfırlansın mı?",
"remember" : "hatırla",
"Alternative Logins" : "Alternatif Girişler",
"Hey there,<br><br>just letting you know that %s shared <strong>%s</strong> with you.<br><a href=\"%s\">View it!</a><br><br>" : "Merhaba, <br><br>%s kullanıcısının sizinle <strong>%s</strong> paylaşımında bulunduğunu bildirmek istedik.<br><a href=\"%s\">Paylaşımı gör!</a><br><br>",
@@ -244,6 +258,10 @@
"Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Lütfen yöneticiniz ile iletişime geçin. Eğer bu örneğin bir yöneticisi iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını yapılandırın. Bu yapılandırmanın bir örneği config/config.sample.php dosyasında verilmiştir.",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Yapılandırmanıza bağlı olarak, bir yönetici olarak bu alan adına güvenmek için aşağıdaki düğmeyi de kullanabilirsiniz.",
"Add \"%s\" as trusted domain" : "\"%s\" alan adını güvenilir olarak ekle",
+ "App update required" : "Uygulama güncellemesi gerekli",
+ "%s will be updated to version %s" : "%s, %s sürümüne güncellenecek",
+ "These apps will be updated:" : "Bu uygulamalar güncellenecek:",
+ "These incompatible apps will be disabled:" : "Bu uyumsuz uygulamalar kapatılacaklar:",
"The theme %s has been disabled." : "%s teması devre dışı bırakıldı.",
"Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "Devam etmeden önce lütfen veritabanının, yapılandırma ve veri klasörlerinin yedeklenmiş olduğundan emin olun.",
"Start update" : "Güncellemeyi başlat",
diff --git a/core/l10n/zh_CN.js b/core/l10n/zh_CN.js
index e82635fe946..4af50e61c13 100644
--- a/core/l10n/zh_CN.js
+++ b/core/l10n/zh_CN.js
@@ -2,6 +2,7 @@ OC.L10N.register(
"core",
{
"Couldn't send mail to following users: %s " : "无法发送邮件到用户: %s ",
+ "Preparing update" : "正在准备更新",
"Turned on maintenance mode" : "启用维护模式",
"Turned off maintenance mode" : "关闭维护模式",
"Maintenance mode is kept active" : "维护模式已被启用",
@@ -13,6 +14,7 @@ OC.L10N.register(
"Repair error: " : "修复错误:",
"Following incompatible apps have been disabled: %s" : "下列不兼容应用已经被禁用:%s",
"Following apps have been disabled: %s" : "下列应用已经被禁用:%s",
+ "Already up to date" : "已经是最新",
"File is too big" : "文件太大",
"Invalid file provided" : "提供了无效文件",
"No image or file provided" : "没有提供图片或文件",
@@ -36,6 +38,13 @@ OC.L10N.register(
"Thu." : "周四",
"Fri." : "周五",
"Sat." : "周六",
+ "Su" : "Su",
+ "Mo" : "Mo",
+ "Tu" : "Tu",
+ "We" : "We",
+ "Th" : "Th",
+ "Fr" : "Fr",
+ "Sa" : "Sa",
"January" : "一月",
"February" : "二月",
"March" : "三月",
@@ -95,6 +104,8 @@ OC.L10N.register(
"Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "你的数据目录和你的文件可能从互联网被访问到。.htaccess 文件不工作。我们强烈建议你配置你的网页服务器,使数据目录不再可访问,或者将数据目录移动到网页服务器根文档目录之外。",
"No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "内存缓存未配置。如果可用,请配置 memcache 来增强性能。更多信息请查看我们的<a href=\"{docLink}\">文档</a> 。",
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "/dev/urandom 无法被 PHP 读取,处于安全原因,这是强烈不推荐的。请查看<a href=\"{docLink}\">文档</a>了解详情。",
+ "Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "你的 PHP 版本 ({version}) 不再被 <a href=\"{phpLink}\"> PHP </a>支持。我们建议您升级您的PHP版本,以便获得 PHP 性能和安全提升。",
+ "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "反向代理头配置不正确,或者您正从一个受信任的代理访问ownCloud。如果你不是通过受信任的代理访问 ownCloud,这将引发一个安全问题,可能由于 ownCloud IP 地址可见导致欺骗攻击。更多信息可以查看我们的 <a href=\"{docLink}\">文档</a>。",
"Error occurred while checking server setup" : "当检查服务器启动时出错",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP 头部没有配置和 \"{expected}\" 的一样。这是一个潜在的安全或者隐私风险,我们调整这项设置。",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "HTTP 严格传输安全(Strict-Transport-Security)报头未配置到至少“{seconds}”秒。处于增强安全性考虑,我们推荐按照<a href=\"{docUrl}\">安全提示</a>启用 HSTS。",
@@ -163,6 +174,7 @@ OC.L10N.register(
"The update was successful. There were warnings." : "更新成功。有警告。",
"The update was successful. Redirecting you to ownCloud now." : "更新成功。正在重定向至 ownCloud。",
"Couldn't reset password because the token is invalid" : "令牌无效,无法重置密码",
+ "Couldn't reset password because the token is expired" : "无法重设密码,因为令牌已过期",
"Couldn't send reset email. Please make sure your username is correct." : "无法发送重置邮件,请检查您的用户名是否正确。",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "此用户名的电子邮件地址不存在导致无法发送重置邮件,请联系管理员。",
"%s password reset" : "重置 %s 的密码",
@@ -236,6 +248,7 @@ OC.L10N.register(
"Please contact your administrator." : "请联系你的管理员。",
"An internal error occured." : "发生了内部错误。",
"Please try again or contact your administrator." : "请重试或联系管理员。",
+ "Wrong password. Reset it?" : "密码错误。要重置么?",
"remember" : "记住",
"Alternative Logins" : "其他登录方式",
"Hey there,<br><br>just letting you know that %s shared <strong>%s</strong> with you.<br><a href=\"%s\">View it!</a><br><br>" : "嗨、你好,<br><br>只想让你知道 %s 分享了 <strong>%s</strong> 给你。<br><a href=\"%s\">现在查看!</a><br><br>",
@@ -247,6 +260,10 @@ OC.L10N.register(
"Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "请联系你的系统管理员。如果你是系统管理员,配置config/config.php文件中参数\"trusted_domain\" 设置。可以在config/config.sample.php文件中找到例子。",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "基于你的配置,作为系统管理员,你可能还能点击下面的按钮来信任这个域。",
"Add \"%s\" as trusted domain" : "添加 \"%s\"为信任域",
+ "App update required" : "必须的应用更新",
+ "%s will be updated to version %s" : "%s 将会更新至版本 %s",
+ "These apps will be updated:" : "以下应用将被更新:",
+ "These incompatible apps will be disabled:" : "这些不兼容的应用程序将被禁用:",
"The theme %s has been disabled." : "%s 主题已被禁用。",
"Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "在继续之前,请确认数据库、配置文件夹和数据文件夹已经备份。",
"Start update" : "开始更新",
diff --git a/core/l10n/zh_CN.json b/core/l10n/zh_CN.json
index d47be1b0c5d..b485c703e36 100644
--- a/core/l10n/zh_CN.json
+++ b/core/l10n/zh_CN.json
@@ -1,5 +1,6 @@
{ "translations": {
"Couldn't send mail to following users: %s " : "无法发送邮件到用户: %s ",
+ "Preparing update" : "正在准备更新",
"Turned on maintenance mode" : "启用维护模式",
"Turned off maintenance mode" : "关闭维护模式",
"Maintenance mode is kept active" : "维护模式已被启用",
@@ -11,6 +12,7 @@
"Repair error: " : "修复错误:",
"Following incompatible apps have been disabled: %s" : "下列不兼容应用已经被禁用:%s",
"Following apps have been disabled: %s" : "下列应用已经被禁用:%s",
+ "Already up to date" : "已经是最新",
"File is too big" : "文件太大",
"Invalid file provided" : "提供了无效文件",
"No image or file provided" : "没有提供图片或文件",
@@ -34,6 +36,13 @@
"Thu." : "周四",
"Fri." : "周五",
"Sat." : "周六",
+ "Su" : "Su",
+ "Mo" : "Mo",
+ "Tu" : "Tu",
+ "We" : "We",
+ "Th" : "Th",
+ "Fr" : "Fr",
+ "Sa" : "Sa",
"January" : "一月",
"February" : "二月",
"March" : "三月",
@@ -93,6 +102,8 @@
"Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "你的数据目录和你的文件可能从互联网被访问到。.htaccess 文件不工作。我们强烈建议你配置你的网页服务器,使数据目录不再可访问,或者将数据目录移动到网页服务器根文档目录之外。",
"No memory cache has been configured. To enhance your performance please configure a memcache if available. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "内存缓存未配置。如果可用,请配置 memcache 来增强性能。更多信息请查看我们的<a href=\"{docLink}\">文档</a> 。",
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "/dev/urandom 无法被 PHP 读取,处于安全原因,这是强烈不推荐的。请查看<a href=\"{docLink}\">文档</a>了解详情。",
+ "Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "你的 PHP 版本 ({version}) 不再被 <a href=\"{phpLink}\"> PHP </a>支持。我们建议您升级您的PHP版本,以便获得 PHP 性能和安全提升。",
+ "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "反向代理头配置不正确,或者您正从一个受信任的代理访问ownCloud。如果你不是通过受信任的代理访问 ownCloud,这将引发一个安全问题,可能由于 ownCloud IP 地址可见导致欺骗攻击。更多信息可以查看我们的 <a href=\"{docLink}\">文档</a>。",
"Error occurred while checking server setup" : "当检查服务器启动时出错",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP 头部没有配置和 \"{expected}\" 的一样。这是一个潜在的安全或者隐私风险,我们调整这项设置。",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "HTTP 严格传输安全(Strict-Transport-Security)报头未配置到至少“{seconds}”秒。处于增强安全性考虑,我们推荐按照<a href=\"{docUrl}\">安全提示</a>启用 HSTS。",
@@ -161,6 +172,7 @@
"The update was successful. There were warnings." : "更新成功。有警告。",
"The update was successful. Redirecting you to ownCloud now." : "更新成功。正在重定向至 ownCloud。",
"Couldn't reset password because the token is invalid" : "令牌无效,无法重置密码",
+ "Couldn't reset password because the token is expired" : "无法重设密码,因为令牌已过期",
"Couldn't send reset email. Please make sure your username is correct." : "无法发送重置邮件,请检查您的用户名是否正确。",
"Couldn't send reset email because there is no email address for this username. Please contact your administrator." : "此用户名的电子邮件地址不存在导致无法发送重置邮件,请联系管理员。",
"%s password reset" : "重置 %s 的密码",
@@ -234,6 +246,7 @@
"Please contact your administrator." : "请联系你的管理员。",
"An internal error occured." : "发生了内部错误。",
"Please try again or contact your administrator." : "请重试或联系管理员。",
+ "Wrong password. Reset it?" : "密码错误。要重置么?",
"remember" : "记住",
"Alternative Logins" : "其他登录方式",
"Hey there,<br><br>just letting you know that %s shared <strong>%s</strong> with you.<br><a href=\"%s\">View it!</a><br><br>" : "嗨、你好,<br><br>只想让你知道 %s 分享了 <strong>%s</strong> 给你。<br><a href=\"%s\">现在查看!</a><br><br>",
@@ -245,6 +258,10 @@
"Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domain\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "请联系你的系统管理员。如果你是系统管理员,配置config/config.php文件中参数\"trusted_domain\" 设置。可以在config/config.sample.php文件中找到例子。",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "基于你的配置,作为系统管理员,你可能还能点击下面的按钮来信任这个域。",
"Add \"%s\" as trusted domain" : "添加 \"%s\"为信任域",
+ "App update required" : "必须的应用更新",
+ "%s will be updated to version %s" : "%s 将会更新至版本 %s",
+ "These apps will be updated:" : "以下应用将被更新:",
+ "These incompatible apps will be disabled:" : "这些不兼容的应用程序将被禁用:",
"The theme %s has been disabled." : "%s 主题已被禁用。",
"Please make sure that the database, the config folder and the data folder have been backed up before proceeding." : "在继续之前,请确认数据库、配置文件夹和数据文件夹已经备份。",
"Start update" : "开始更新",
diff --git a/core/l10n/zh_TW.js b/core/l10n/zh_TW.js
index 29ef83f2614..e7fcff74d76 100644
--- a/core/l10n/zh_TW.js
+++ b/core/l10n/zh_TW.js
@@ -2,8 +2,10 @@ OC.L10N.register(
"core",
{
"Couldn't send mail to following users: %s " : "無法寄送郵件給這些使用者:%s",
+ "Preparing update" : "準備更新",
"Turned on maintenance mode" : "已啓用維護模式",
"Turned off maintenance mode" : "已停用維護模式",
+ "Maintenance mode is kept active" : "維護模式維持在開啟狀態",
"Updated database" : "已更新資料庫",
"Checked database schema update" : "已檢查資料庫格式更新",
"Checked database schema update for apps" : "已檢查應用程式的資料庫格式更新",
diff --git a/core/l10n/zh_TW.json b/core/l10n/zh_TW.json
index bf1e1a5ff5b..2b42231bd7b 100644
--- a/core/l10n/zh_TW.json
+++ b/core/l10n/zh_TW.json
@@ -1,7 +1,9 @@
{ "translations": {
"Couldn't send mail to following users: %s " : "無法寄送郵件給這些使用者:%s",
+ "Preparing update" : "準備更新",
"Turned on maintenance mode" : "已啓用維護模式",
"Turned off maintenance mode" : "已停用維護模式",
+ "Maintenance mode is kept active" : "維護模式維持在開啟狀態",
"Updated database" : "已更新資料庫",
"Checked database schema update" : "已檢查資料庫格式更新",
"Checked database schema update for apps" : "已檢查應用程式的資料庫格式更新",
diff --git a/core/register_command.php b/core/register_command.php
index 984e1b97f67..72c7b28e9ae 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -62,6 +62,23 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
$application->add(new OC\Core\Command\Log\Manage(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Log\OwnCloud(\OC::$server->getConfig()));
+ $view = new \OC\Files\View();
+ $util = new \OC\Encryption\Util(
+ $view,
+ \OC::$server->getUserManager(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getConfig()
+ );
+ $application->add(new OC\Core\Command\Encryption\ChangeKeyStorageRoot(
+ $view,
+ \OC::$server->getUserManager(),
+ \OC::$server->getConfig(),
+ $util,
+ new \Symfony\Component\Console\Helper\QuestionHelper()
+ )
+ );
+ $application->add(new OC\Core\Command\Encryption\ShowKeyStorageRoot($util));
+
$application->add(new OC\Core\Command\Maintenance\MimeTypesJS());
$application->add(new OC\Core\Command\Maintenance\Mode(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Maintenance\Repair(new \OC\Repair(\OC\Repair::getRepairSteps()), \OC::$server->getConfig()));
diff --git a/lib/autoloader.php b/lib/autoloader.php
index 23285f61e73..d7649781ea1 100644
--- a/lib/autoloader.php
+++ b/lib/autoloader.php
@@ -34,13 +34,34 @@ class Autoloader {
private $classPaths = array();
+ private $validRoots = [];
+
/**
* Optional low-latency memory cache for class to path mapping.
+ *
* @var \OC\Memcache\Cache
*/
protected $memoryCache;
/**
+ * Autoloader constructor.
+ *
+ * @param string[] $validRoots
+ */
+ public function __construct(array $validRoots) {
+ $this->validRoots = $validRoots;
+ }
+
+ /**
+ * Add a path to the list of valid php roots for auto loading
+ *
+ * @param string $root
+ */
+ public function addValidRoot($root) {
+ $this->validRoots[] = $root;
+ }
+
+ /**
* disable the usage of the global classpath \OC::$CLASSPATH
*/
public function disableGlobalClassPath() {
@@ -102,6 +123,15 @@ class Autoloader {
return $paths;
}
+ protected function isValidPath($fullPath) {
+ foreach ($this->validRoots as $root) {
+ if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') {
+ return true;
+ }
+ }
+ throw new \Exception('Path not allowed: '. $fullPath);
+ }
+
/**
* Load the specified class
*
@@ -119,7 +149,7 @@ class Autoloader {
$pathsToRequire = array();
foreach ($this->findClass($class) as $path) {
$fullPath = stream_resolve_include_path($path);
- if ($fullPath) {
+ if ($fullPath && $this->isValidPath($fullPath)) {
$pathsToRequire[] = $fullPath;
}
}
@@ -138,6 +168,7 @@ class Autoloader {
/**
* Sets the optional low-latency cache for class to path mapping.
+ *
* @param \OC\Memcache\Cache $memoryCache Instance of memory cache.
*/
public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) {
diff --git a/lib/base.php b/lib/base.php
index aceac2e53c3..9cf0228bbd9 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -115,9 +115,6 @@ class OC {
* the app path list is empty or contains an invalid path
*/
public static function initPaths() {
- // calculate the root directories
- OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
-
// ensure we can find OC_Config
set_include_path(
OC::$SERVERROOT . '/lib' . PATH_SEPARATOR .
@@ -519,10 +516,20 @@ class OC {
}
public static function init() {
+ // calculate the root directories
+ OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
+
// register autoloader
$loaderStart = microtime(true);
require_once __DIR__ . '/autoloader.php';
- self::$loader = new \OC\Autoloader();
+ self::$loader = new \OC\Autoloader([
+ OC::$SERVERROOT . '/lib',
+ OC::$SERVERROOT . '/core',
+ OC::$SERVERROOT . '/settings',
+ OC::$SERVERROOT . '/ocs',
+ OC::$SERVERROOT . '/ocs-provider',
+ OC::$SERVERROOT . '/3rdparty'
+ ]);
spl_autoload_register(array(self::$loader, 'load'));
$loaderEnd = microtime(true);
@@ -545,6 +552,10 @@ class OC {
exit();
}
+ foreach(OC::$APPSROOTS as $appRoot) {
+ self::$loader->addValidRoot($appRoot['path']);
+ }
+
// setup the basic server
self::$server = new \OC\Server(\OC::$WEBROOT);
\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
diff --git a/lib/l10n/id.js b/lib/l10n/id.js
index 432ea5c0192..2114b34eddd 100644
--- a/lib/l10n/id.js
+++ b/lib/l10n/id.js
@@ -49,6 +49,7 @@ OC.L10N.register(
"Can't read file" : "Tidak dapat membaca berkas",
"App directory already exists" : "Direktori Apl sudah ada",
"Can't create app folder. Please fix permissions. %s" : "Tidak dapat membuat folder apl. Silakan perbaiki perizinan. %s",
+ "Archive does not contain a directory named %s" : "Arsip tidak berisi direktori yang bernama %s",
"No source specified when installing app" : "Tidak ada sumber yang ditentukan saat menginstal apl",
"No href specified when installing app from http" : "Href tidak ditentukan saat menginstal apl dari http",
"No path specified when installing app from local file" : "Lokasi tidak ditentukan saat menginstal apl dari berkas lokal",
diff --git a/lib/l10n/id.json b/lib/l10n/id.json
index 6aeffa363da..cdc17b6ce8e 100644
--- a/lib/l10n/id.json
+++ b/lib/l10n/id.json
@@ -47,6 +47,7 @@
"Can't read file" : "Tidak dapat membaca berkas",
"App directory already exists" : "Direktori Apl sudah ada",
"Can't create app folder. Please fix permissions. %s" : "Tidak dapat membuat folder apl. Silakan perbaiki perizinan. %s",
+ "Archive does not contain a directory named %s" : "Arsip tidak berisi direktori yang bernama %s",
"No source specified when installing app" : "Tidak ada sumber yang ditentukan saat menginstal apl",
"No href specified when installing app from http" : "Href tidak ditentukan saat menginstal apl dari http",
"No path specified when installing app from local file" : "Lokasi tidak ditentukan saat menginstal apl dari berkas lokal",
diff --git a/lib/private/activitymanager.php b/lib/private/activitymanager.php
index a973db7206f..fc250173536 100644
--- a/lib/private/activitymanager.php
+++ b/lib/private/activitymanager.php
@@ -244,15 +244,27 @@ class ActivityManager implements IManager {
* @return array
*/
public function getNotificationTypes($languageCode) {
+ $filesNotificationTypes = [];
+ $sharingNotificationTypes = [];
+
$notificationTypes = array();
foreach ($this->getExtensions() as $c) {
$result = $c->getNotificationTypes($languageCode);
if (is_array($result)) {
+ if (class_exists('\OCA\Files\Activity') && $c instanceof \OCA\Files\Activity) {
+ $filesNotificationTypes = $result;
+ continue;
+ }
+ if (class_exists('\OCA\Files_Sharing\Activity') && $c instanceof \OCA\Files_Sharing\Activity) {
+ $sharingNotificationTypes = $result;
+ continue;
+ }
+
$notificationTypes = array_merge($notificationTypes, $result);
}
}
- return $notificationTypes;
+ return array_merge($filesNotificationTypes, $sharingNotificationTypes, $notificationTypes);
}
/**
diff --git a/lib/private/appframework/http.php b/lib/private/appframework/http.php
index e7b0d1e2cab..dee9818f4bc 100644
--- a/lib/private/appframework/http.php
+++ b/lib/private/appframework/http.php
@@ -121,7 +121,7 @@ class Http extends BaseHttp {
// if etag or lastmodified have not changed, return a not modified
if ((isset($this->server['HTTP_IF_NONE_MATCH'])
- && trim($this->server['HTTP_IF_NONE_MATCH']) === $ETag)
+ && trim(trim($this->server['HTTP_IF_NONE_MATCH']), '"') === (string)$ETag)
||
diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php
index a2109439177..b430673f9a9 100644
--- a/lib/private/appframework/http/request.php
+++ b/lib/private/appframework/http/request.php
@@ -9,6 +9,7 @@
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Thomas Tanghus <thomas@tanghus.net>
* @author Vincent Petry <pvince81@owncloud.com>
+ * @author Robin McCorkell <rmccorkell@owncloud.com>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0
@@ -71,6 +72,9 @@ class Request implements \ArrayAccess, \Countable, IRequest {
/** @var ICrypto */
protected $crypto;
+ /** @var bool */
+ protected $contentDecoded = false;
+
/**
* @param array $vars An associative array with the following optional values:
* - array 'urlParams' the parameters which were matched from the URL
@@ -109,27 +113,6 @@ class Request implements \ArrayAccess, \Countable, IRequest {
: array();
}
- // 'application/json' must be decoded manually.
- if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
- $params = json_decode(file_get_contents($this->inputStream), true);
- if(count($params) > 0) {
- $this->items['params'] = $params;
- if($vars['method'] === 'POST') {
- $this->items['post'] = $params;
- }
- }
- // Handle application/x-www-form-urlencoded for methods other than GET
- // or post correctly
- } elseif($vars['method'] !== 'GET'
- && $vars['method'] !== 'POST'
- && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
-
- parse_str(file_get_contents($this->inputStream), $params);
- if(is_array($params)) {
- $this->items['params'] = $params;
- }
- }
-
$this->items['parameters'] = array_merge(
$this->items['get'],
$this->items['post'],
@@ -237,24 +220,19 @@ class Request implements \ArrayAccess, \Countable, IRequest {
if($this->method !== strtoupper($name)) {
throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method));
}
+ return $this->getContent();
case 'files':
case 'server':
case 'env':
case 'cookies':
- case 'parameters':
- case 'params':
case 'urlParams':
- if(in_array($name, array('put', 'patch'))) {
- return $this->getContent();
- } else {
- return isset($this->items[$name])
- ? $this->items[$name]
- : null;
- }
- break;
case 'method':
- return $this->items['method'];
- break;
+ return isset($this->items[$name])
+ ? $this->items[$name]
+ : null;
+ case 'parameters':
+ case 'params':
+ return $this->getContent();
default;
return isset($this[$name])
? $this[$name]
@@ -396,11 +374,48 @@ class Request implements \ArrayAccess, \Countable, IRequest {
$this->content = false;
return fopen($this->inputStream, 'rb');
} else {
- return $this->parameters;
+ $this->decodeContent();
+ return $this->items['parameters'];
}
}
/**
+ * Attempt to decode the content and populate parameters
+ */
+ protected function decodeContent() {
+ if ($this->contentDecoded) {
+ return;
+ }
+ $params = [];
+
+ // 'application/json' must be decoded manually.
+ if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
+ $params = json_decode(file_get_contents($this->inputStream), true);
+ if(count($params) > 0) {
+ $this->items['params'] = $params;
+ if($this->method === 'POST') {
+ $this->items['post'] = $params;
+ }
+ }
+
+ // Handle application/x-www-form-urlencoded for methods other than GET
+ // or post correctly
+ } elseif($this->method !== 'GET'
+ && $this->method !== 'POST'
+ && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
+
+ parse_str(file_get_contents($this->inputStream), $params);
+ if(is_array($params)) {
+ $this->items['params'] = $params;
+ }
+ }
+
+ $this->items['parameters'] = array_merge($this->items['parameters'], $params);
+ $this->contentDecoded = true;
+ }
+
+
+ /**
* Checks if the CSRF check was correct
* @return bool true if CSRF check passed
* @see OC_Util::callRegister()
diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php
index b754462d9b0..d0c094538b0 100644
--- a/lib/private/encryption/keys/storage.php
+++ b/lib/private/encryption/keys/storage.php
@@ -27,11 +27,13 @@ namespace OC\Encryption\Keys;
use OC\Encryption\Util;
use OC\Files\Filesystem;
use OC\Files\View;
-use OCP\Encryption\Exceptions\GenericEncryptionException;
use OCP\Encryption\Keys\IStorage;
class Storage implements IStorage {
+ // hidden file which indicate that the folder is a valid key storage
+ const KEY_STORAGE_MARKER = '.oc_key_storage';
+
/** @var View */
private $view;
@@ -42,6 +44,10 @@ class Storage implements IStorage {
/** @var string */
private $keys_base_dir;
+ // root of the key storage default is empty which means that we use the data folder
+ /** @var string */
+ private $root_dir;
+
/** @var string */
private $encryption_base_dir;
@@ -58,6 +64,7 @@ class Storage implements IStorage {
$this->encryption_base_dir = '/files_encryption';
$this->keys_base_dir = $this->encryption_base_dir .'/keys';
+ $this->root_dir = $this->util->getKeyStorageRoot();
}
/**
@@ -162,13 +169,13 @@ class Storage implements IStorage {
protected function constructUserKeyPath($encryptionModuleId, $keyId, $uid) {
if ($uid === null) {
- $path = $this->encryption_base_dir . '/' . $encryptionModuleId . '/' . $keyId;
+ $path = $this->root_dir . '/' . $this->encryption_base_dir . '/' . $encryptionModuleId . '/' . $keyId;
} else {
- $path = '/' . $uid . $this->encryption_base_dir . '/'
+ $path = $this->root_dir . '/' . $uid . $this->encryption_base_dir . '/'
. $encryptionModuleId . '/' . $uid . '.' . $keyId;
}
- return $path;
+ return \OC\Files\Filesystem::normalizePath($path);
}
/**
@@ -227,9 +234,9 @@ class Storage implements IStorage {
// in case of system wide mount points the keys are stored directly in the data directory
if ($this->util->isSystemWideMountPoint($filename, $owner)) {
- $keyPath = $this->keys_base_dir . $filename . '/';
+ $keyPath = $this->root_dir . '/' . $this->keys_base_dir . $filename . '/';
} else {
- $keyPath = '/' . $owner . $this->keys_base_dir . $filename . '/';
+ $keyPath = $this->root_dir . '/' . $owner . $this->keys_base_dir . $filename . '/';
}
return Filesystem::normalizePath($keyPath . $encryptionModuleId . '/', false);
@@ -290,12 +297,12 @@ class Storage implements IStorage {
$systemWideMountPoint = $this->util->isSystemWideMountPoint($relativePath, $owner);
if ($systemWideMountPoint) {
- $systemPath = $this->keys_base_dir . $relativePath . '/';
+ $systemPath = $this->root_dir . '/' . $this->keys_base_dir . $relativePath . '/';
} else {
- $systemPath = '/' . $owner . $this->keys_base_dir . $relativePath . '/';
+ $systemPath = $this->root_dir . '/' . $owner . $this->keys_base_dir . $relativePath . '/';
}
- return $systemPath;
+ return Filesystem::normalizePath($systemPath, false);
}
/**
diff --git a/lib/private/encryption/manager.php b/lib/private/encryption/manager.php
index 1e0a065e25a..c004dfda0d9 100644
--- a/lib/private/encryption/manager.php
+++ b/lib/private/encryption/manager.php
@@ -25,14 +25,12 @@
namespace OC\Encryption;
+use OC\Encryption\Keys\Storage;
use OC\Files\Filesystem;
-use OC\Files\Storage\Shared;
-use OC\Files\Storage\Wrapper\Encryption;
use OC\Files\View;
-use OC\Search\Provider\File;
+use OC\ServiceUnavailableException;
use OCP\Encryption\IEncryptionModule;
use OCP\Encryption\IManager;
-use OCP\Files\Mount\IMountPoint;
use OCP\IConfig;
use OCP\IL10N;
use OCP\ILogger;
@@ -51,16 +49,26 @@ class Manager implements IManager {
/** @var Il10n */
protected $l;
+ /** @var View */
+ protected $rootView;
+
+ /** @var Util */
+ protected $util;
+
/**
* @param IConfig $config
* @param ILogger $logger
* @param IL10N $l10n
+ * @param View $rootView
+ * @param Util $util
*/
- public function __construct(IConfig $config, ILogger $logger, IL10N $l10n) {
+ public function __construct(IConfig $config, ILogger $logger, IL10N $l10n, View $rootView, Util $util) {
$this->encryptionModules = array();
$this->config = $config;
$this->logger = $logger;
$this->l = $l10n;
+ $this->rootView = $rootView;
+ $this->util = $util;
}
/**
@@ -82,7 +90,8 @@ class Manager implements IManager {
/**
* check if new encryption is ready
*
- * @return boolean
+ * @return bool
+ * @throws ServiceUnavailableException
*/
public function isReady() {
// check if we are still in transit between the old and the new encryption
@@ -94,6 +103,11 @@ class Manager implements IManager {
$this->logger->warning($warning);
return false;
}
+
+ if ($this->isKeyStorageReady() === false) {
+ throw new ServiceUnavailableException('Key Storage is not ready');
+ }
+
return true;
}
@@ -221,6 +235,31 @@ class Manager implements IManager {
\OC::$server->getGroupManager(),
\OC::$server->getConfig()
);
- \OC\Files\Filesystem::addStorageWrapper('oc_encryption', array($util, 'wrapStorage'), 2);
+ Filesystem::addStorageWrapper('oc_encryption', array($util, 'wrapStorage'), 2);
}
+
+
+ /**
+ * check if key storage is ready
+ *
+ * @return bool
+ */
+ protected function isKeyStorageReady() {
+
+ $rootDir = $this->util->getKeyStorageRoot();
+
+ // the default root is always valid
+ if ($rootDir === '') {
+ return true;
+ }
+
+ // check if key storage is mounted correctly
+ if ($this->rootView->file_exists($rootDir . '/' . Storage::KEY_STORAGE_MARKER)) {
+ return true;
+ }
+
+ return false;
+ }
+
+
}
diff --git a/lib/private/encryption/util.php b/lib/private/encryption/util.php
index d0733941a35..90ae8259972 100644
--- a/lib/private/encryption/util.php
+++ b/lib/private/encryption/util.php
@@ -59,7 +59,7 @@ class Util {
protected $blockSize = 8192;
/** @var View */
- protected $view;
+ protected $rootView;
/** @var array */
protected $ocHeaderKeys;
@@ -78,13 +78,13 @@ class Util {
/**
*
- * @param \OC\Files\View $view
+ * @param View $rootView
* @param \OC\User\Manager $userManager
* @param \OC\Group\Manager $groupManager
* @param IConfig $config
*/
public function __construct(
- \OC\Files\View $view,
+ View $rootView,
\OC\User\Manager $userManager,
\OC\Group\Manager $groupManager,
IConfig $config) {
@@ -93,7 +93,7 @@ class Util {
self::HEADER_ENCRYPTION_MODULE_KEY
];
- $this->view = $view;
+ $this->rootView = $rootView;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->config = $config;
@@ -167,7 +167,7 @@ class Util {
while ($dirList) {
$dir = array_pop($dirList);
- $content = $this->view->getDirectoryContent($dir);
+ $content = $this->rootView->getDirectoryContent($dir);
foreach ($content as $c) {
if ($c->getType() === 'dir') {
@@ -332,10 +332,22 @@ class Util {
* @return boolean
*/
public function isExcluded($path) {
- $normalizedPath = \OC\Files\Filesystem::normalizePath($path);
+ $normalizedPath = Filesystem::normalizePath($path);
$root = explode('/', $normalizedPath, 4);
if (count($root) > 1) {
+ // detect alternative key storage root
+ $rootDir = $this->getKeyStorageRoot();
+ if ($rootDir !== '' &&
+ 0 === strpos(
+ Filesystem::normalizePath($path),
+ Filesystem::normalizePath($rootDir)
+ )
+ ) {
+ return true;
+ }
+
+
//detect system wide folders
if (in_array($root[1], $this->excludedPaths)) {
return true;
@@ -364,6 +376,24 @@ class Util {
}
/**
+ * set new key storage root
+ *
+ * @param string $root new key store root relative to the data folder
+ */
+ public function setKeyStorageRoot($root) {
+ $this->config->setAppValue('core', 'encryption_key_storage_root', $root);
+ }
+
+ /**
+ * get key storage root
+ *
+ * @return string key storage root
+ */
+ public function getKeyStorageRoot() {
+ return $this->config->getAppValue('core', 'encryption_key_storage_root', '');
+ }
+
+ /**
* Wraps the given storage when it is not a shared storage
*
* @param string $mountPoint
diff --git a/lib/private/files/storage/storagefactory.php b/lib/private/files/storage/storagefactory.php
index 62b393c845c..e8df5090f09 100644
--- a/lib/private/files/storage/storagefactory.php
+++ b/lib/private/files/storage/storagefactory.php
@@ -99,6 +99,9 @@ class StorageFactory implements IStorageFactory {
}, $wrappers);
foreach ($wrappers as $wrapper) {
$storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint);
+ if (!($storage instanceof \OCP\Files\Storage)) {
+ throw new \Exception('Invalid result from storage wrapper');
+ }
}
return $storage;
}
diff --git a/lib/private/preview.php b/lib/private/preview.php
index 5dcab476a4f..978da1161c2 100644
--- a/lib/private/preview.php
+++ b/lib/private/preview.php
@@ -38,6 +38,9 @@ class Preview {
//the thumbnail folder
const THUMBNAILS_FOLDER = 'thumbnails';
+ const MODE_FILL = 'fill';
+ const MODE_COVER = 'cover';
+
//config
private $maxScaleFactor;
/** @var int maximum width allowed for a preview */
@@ -56,6 +59,7 @@ class Preview {
private $scalingUp;
private $mimeType;
private $keepAspect = false;
+ private $mode = self::MODE_FILL;
//used to calculate the size of the preview to generate
/** @var int $maxPreviewWidth max width a preview can have */
@@ -332,6 +336,19 @@ class Preview {
}
/**
+ * Set whether to cover or fill the specified dimensions
+ *
+ * @param string $mode
+ *
+ * @return \OC\Preview
+ */
+ public function setMode($mode) {
+ $this->mode = $mode;
+
+ return $this;
+ }
+
+ /**
* Sets whether we need to generate a preview which keeps the aspect ratio of the original file
*
* @param bool $keepAspect
@@ -531,14 +548,22 @@ class Preview {
* @param int $askedWidth
* @param int $askedHeight
*
+ * @param int $originalWidth
+ * @param int $originalHeight
* @return \int[]
*/
- private function applyAspectRatio($askedWidth, $askedHeight) {
- $originalRatio = $this->maxPreviewWidth / $this->maxPreviewHeight;
+ private function applyAspectRatio($askedWidth, $askedHeight, $originalWidth = 0, $originalHeight = 0) {
+ if(!$originalWidth){
+ $originalWidth= $this->maxPreviewWidth;
+ }
+ if (!$originalHeight) {
+ $originalHeight = $this->maxPreviewHeight;
+ }
+ $originalRatio = $originalWidth / $originalHeight;
// Defines the box in which the preview has to fit
$scaleFactor = $this->scalingUp ? $this->maxScaleFactor : 1;
- $askedWidth = min($askedWidth, $this->maxPreviewWidth * $scaleFactor);
- $askedHeight = min($askedHeight, $this->maxPreviewHeight * $scaleFactor);
+ $askedWidth = min($askedWidth, $originalWidth * $scaleFactor);
+ $askedHeight = min($askedHeight, $originalHeight * $scaleFactor);
if ($askedWidth / $originalRatio < $askedHeight) {
// width restricted
@@ -551,6 +576,32 @@ class Preview {
}
/**
+ * Resizes the boundaries to cover the area
+ *
+ * @param int $askedWidth
+ * @param int $askedHeight
+ * @param int $previewWidth
+ * @param int $previewHeight
+ * @return \int[]
+ */
+ private function applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight) {
+ $originalRatio = $previewWidth / $previewHeight;
+ // Defines the box in which the preview has to fit
+ $scaleFactor = $this->scalingUp ? $this->maxScaleFactor : 1;
+ $askedWidth = min($askedWidth, $previewWidth * $scaleFactor);
+ $askedHeight = min($askedHeight, $previewHeight * $scaleFactor);
+
+ if ($askedWidth / $originalRatio > $askedHeight) {
+ // height restricted
+ $askedHeight = round($askedWidth / $originalRatio);
+ } else {
+ $askedWidth = round($askedHeight * $originalRatio);
+ }
+
+ return [(int)$askedWidth, (int)$askedHeight];
+ }
+
+ /**
* Makes sure an upscaled preview doesn't end up larger than the max dimensions defined in the
* config
*
@@ -791,7 +842,15 @@ class Preview {
*/
if ($this->keepAspect) {
list($askedWidth, $askedHeight) =
- $this->applyAspectRatio($askedWidth, $askedHeight);
+ $this->applyAspectRatio($askedWidth, $askedHeight, $previewWidth, $previewHeight);
+ }
+
+ if ($this->mode === self::MODE_COVER) {
+ list($scaleWidth, $scaleHeight) =
+ $this->applyCover($askedWidth, $askedHeight, $previewWidth, $previewHeight);
+ } else {
+ $scaleWidth = $askedWidth;
+ $scaleHeight = $askedHeight;
}
/**
@@ -799,7 +858,7 @@ class Preview {
* Takes the scaling ratio into consideration
*/
list($newPreviewWidth, $newPreviewHeight) = $this->scale(
- $image, $askedWidth, $askedHeight, $previewWidth, $previewHeight
+ $image, $scaleWidth, $scaleHeight, $previewWidth, $previewHeight
);
// The preview has been resized and should now have the asked dimensions
@@ -1000,6 +1059,9 @@ class Preview {
if ($this->keepAspect && !$isMaxPreview) {
$previewPath .= '-with-aspect';
}
+ if ($this->mode === self::MODE_COVER) {
+ $previewPath .= '-cover';
+ }
$previewPath .= '.png';
return $previewPath;
diff --git a/lib/private/route/router.php b/lib/private/route/router.php
index 33669452f2d..7b7849a6da0 100644
--- a/lib/private/route/router.php
+++ b/lib/private/route/router.php
@@ -169,8 +169,9 @@ class Router implements IRouter {
$this->useCollection('root');
require_once 'settings/routes.php';
require_once 'core/routes.php';
-
- // include ocs routes
+ }
+ if ($this->loaded) {
+ // include ocs routes, must be loaded last for /ocs prefix
require_once 'ocs/routes.php';
$collection = $this->getCollection('ocs');
$collection->addPrefix('/ocs');
diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php
index d61c7f29327..4d470f69a66 100644
--- a/lib/private/security/certificatemanager.php
+++ b/lib/private/security/certificatemanager.php
@@ -27,6 +27,7 @@ namespace OC\Security;
use OC\Files\Filesystem;
use OCP\ICertificateManager;
+use OCP\IConfig;
/**
* Manage trusted certificates for users
@@ -43,12 +44,19 @@ class CertificateManager implements ICertificateManager {
protected $view;
/**
+ * @var IConfig
+ */
+ protected $config;
+
+ /**
* @param string $uid
* @param \OC\Files\View $view relative zu data/
+ * @param IConfig $config
*/
- public function __construct($uid, \OC\Files\View $view) {
+ public function __construct($uid, \OC\Files\View $view, IConfig $config) {
$this->uid = $uid;
$this->view = $view;
+ $this->config = $config;
}
/**
@@ -57,6 +65,11 @@ class CertificateManager implements ICertificateManager {
* @return \OCP\ICertificate[]
*/
public function listCertificates() {
+
+ if (!$this->config->getSystemValue('installed', false)) {
+ return array();
+ }
+
$path = $this->getPathToCertificates() . 'uploads/';
if (!$this->view->is_dir($path)) {
return array();
diff --git a/lib/private/server.php b/lib/private/server.php
index a47fa2e43f9..a741f33eb3d 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -91,12 +91,25 @@ class Server extends SimpleContainer implements IServerContainer {
});
$this->registerService('EncryptionManager', function (Server $c) {
- return new Encryption\Manager($c->getConfig(), $c->getLogger(), $c->getL10N('core'));
+ $view = new View();
+ $util = new Encryption\Util(
+ $view,
+ $c->getUserManager(),
+ $c->getGroupManager(),
+ $c->getConfig()
+ );
+ return new Encryption\Manager(
+ $c->getConfig(),
+ $c->getLogger(),
+ $c->getL10N('core'),
+ new View(),
+ $util
+ );
});
$this->registerService('EncryptionFileHelper', function (Server $c) {
- $util = new \OC\Encryption\Util(
- new \OC\Files\View(),
+ $util = new Encryption\Util(
+ new View(),
$c->getUserManager(),
$c->getGroupManager(),
$c->getConfig()
@@ -105,8 +118,8 @@ class Server extends SimpleContainer implements IServerContainer {
});
$this->registerService('EncryptionKeyStorage', function (Server $c) {
- $view = new \OC\Files\View();
- $util = new \OC\Encryption\Util(
+ $view = new View();
+ $util = new Encryption\Util(
$view,
$c->getUserManager(),
$c->getGroupManager(),
@@ -326,7 +339,7 @@ class Server extends SimpleContainer implements IServerContainer {
$uid = $user ? $user : null;
return new ClientService(
$c->getConfig(),
- new \OC\Security\CertificateManager($uid, new \OC\Files\View())
+ new \OC\Security\CertificateManager($uid, new View(), $c->getConfig())
);
});
$this->registerService('EventLogger', function (Server $c) {
@@ -839,7 +852,7 @@ class Server extends SimpleContainer implements IServerContainer {
}
$userId = $user->getUID();
}
- return new CertificateManager($userId, new \OC\Files\View());
+ return new CertificateManager($userId, new View(), $this->getConfig());
}
/**
diff --git a/lib/private/util.php b/lib/private/util.php
index edd375b5c36..0fda55496dc 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -1145,6 +1145,7 @@ class OC_Util {
* @throws \OC\HintException If the test file can't get written.
*/
public function isHtaccessWorking(\OCP\IConfig $config) {
+
if (\OC::$CLI || !$config->getSystemValue('check_for_working_htaccess', true)) {
return true;
}
diff --git a/settings/controller/checksetupcontroller.php b/settings/controller/checksetupcontroller.php
index 33f94fe4238..ca4eb255f6b 100644
--- a/settings/controller/checksetupcontroller.php
+++ b/settings/controller/checksetupcontroller.php
@@ -143,7 +143,7 @@ class CheckSetupController extends Controller {
}
$features = (string)$this->l10n->t('installing and updating apps via the app store or Federated Cloud Sharing');
- if(OC_Util::getEditionString() !== '') {
+ if(!$this->config->getSystemValue('appstoreenabled', true)) {
$features = (string)$this->l10n->t('Federated Cloud Sharing');
}
diff --git a/settings/l10n/hu_HU.js b/settings/l10n/hu_HU.js
index 4532c5c243e..cb0400e63b4 100644
--- a/settings/l10n/hu_HU.js
+++ b/settings/l10n/hu_HU.js
@@ -27,6 +27,7 @@ OC.L10N.register(
"No user supplied" : "Nincs megadva felhasználó",
"Please provide an admin recovery password, otherwise all user data will be lost" : "Adja meg az admin helyreállítási jelszót, máskülönben az összes felhasználói adat elveszik!",
"Wrong admin recovery password. Please check the password and try again." : "Hibás admin helyreállítási jelszó. Ellenőrizze a jelszót és próbálja újra!",
+ "Backend doesn't support password change, but the user's encryption key was successfully updated." : "A háttér-alrendszer nem támogatja a jelszómódosítást, de felhasználó titkosítási kulcsát sikeresen frissítettük.",
"Unable to change password" : "Nem sikerült megváltoztatni a jelszót",
"Enabled" : "Engedélyezve",
"Not enabled" : "Tiltva",
@@ -115,7 +116,10 @@ OC.L10N.register(
"The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "A 'fileinfo' PHP modul hiányzik. Erősen javasolt ennek a modulnak a telepítése, mert ezzel lényegesen jobb a MIME-típusok felismerése.",
"System locale can not be set to a one which supports UTF-8." : "A rendszer lokalizációs állományai között nem sikerült olyat beállítani, ami támogatja az UTF-8-at.",
"This means that there might be problems with certain characters in file names." : "Ez azt jelenti, hogy probléma lehet bizonyos karakterekkel a fájlnevekben.",
+ "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "Feltétlenül javasoljuk, hogy telepítse a szükséges csomagokat ahhoz, hogy a rendszere támogassa a következő lokalizációk valamelyikét: %s",
+ "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Ha a telepítése nem a webkiszolgáló gyökerében van, és a rendszer cron szolgáltatását használja, akkor problémák lehetnek az URL-ek képzésével. Ezek elkerülése érdekében állítsa be a config.php-ban az \"overwrite.cli.url\" paramétert a telepítés által használt webútvonalra. (Javasolt beállítás: \"%s\")",
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Az ütemezett feladat (cronjob) nem futott le parancssorból. A következő hibák tűntek fel:",
+ "All checks passed." : "Minden ellenőrzés sikeres.",
"Open documentation" : "Dokumentáció megnyitása",
"Allow apps to use the Share API" : "Lehetővé teszi, hogy a programmodulok is használhassák a megosztást",
"Allow users to share via link" : "Engedjük meg az állományok linkekkel történő megosztását",
@@ -138,6 +142,8 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "A cron.php webcron szolgáltatásként van regisztrálva, hogy 15 percenként egyszer lefuttassa a cron.php-t.",
"Use system's cron service to call the cron.php file every 15 minutes." : "A rendszer cron szolgáltatását használjuk, mely a cron.php állományt futtatja le 15 percenként.",
"Enable server-side encryption" : "Szerveroldali titkosítás engedélyezése",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "A szerveroldali titkosítás egyirányú folyamat. Ha egyszer engedélyezve lett a titkosítás, akkor onnantól kezdve a szerveren az összes fájl titkosításra kerül, melyet később nem lehet visszafordítani.",
+ "This is the final warning: Do you really want to enable encryption?" : "Ez az utolsó figyelmeztetés: Biztosan szeretnéd engedélyezni a titkosítást?",
"Enable encryption" : "Titkosítás engedélyezése",
"No encryption module loaded, please enable an encryption module in the app menu." : "Nincs titkosítási modul betöltve, kérjük engedélyezd a titkosítási modult az alkalmazások menüben.",
"Select default encryption module:" : "Alapértelmezett titkosítási modul:",
diff --git a/settings/l10n/hu_HU.json b/settings/l10n/hu_HU.json
index a416a2f33ed..34ea7fc681d 100644
--- a/settings/l10n/hu_HU.json
+++ b/settings/l10n/hu_HU.json
@@ -25,6 +25,7 @@
"No user supplied" : "Nincs megadva felhasználó",
"Please provide an admin recovery password, otherwise all user data will be lost" : "Adja meg az admin helyreállítási jelszót, máskülönben az összes felhasználói adat elveszik!",
"Wrong admin recovery password. Please check the password and try again." : "Hibás admin helyreállítási jelszó. Ellenőrizze a jelszót és próbálja újra!",
+ "Backend doesn't support password change, but the user's encryption key was successfully updated." : "A háttér-alrendszer nem támogatja a jelszómódosítást, de felhasználó titkosítási kulcsát sikeresen frissítettük.",
"Unable to change password" : "Nem sikerült megváltoztatni a jelszót",
"Enabled" : "Engedélyezve",
"Not enabled" : "Tiltva",
@@ -113,7 +114,10 @@
"The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "A 'fileinfo' PHP modul hiányzik. Erősen javasolt ennek a modulnak a telepítése, mert ezzel lényegesen jobb a MIME-típusok felismerése.",
"System locale can not be set to a one which supports UTF-8." : "A rendszer lokalizációs állományai között nem sikerült olyat beállítani, ami támogatja az UTF-8-at.",
"This means that there might be problems with certain characters in file names." : "Ez azt jelenti, hogy probléma lehet bizonyos karakterekkel a fájlnevekben.",
+ "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "Feltétlenül javasoljuk, hogy telepítse a szükséges csomagokat ahhoz, hogy a rendszere támogassa a következő lokalizációk valamelyikét: %s",
+ "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Ha a telepítése nem a webkiszolgáló gyökerében van, és a rendszer cron szolgáltatását használja, akkor problémák lehetnek az URL-ek képzésével. Ezek elkerülése érdekében állítsa be a config.php-ban az \"overwrite.cli.url\" paramétert a telepítés által használt webútvonalra. (Javasolt beállítás: \"%s\")",
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Az ütemezett feladat (cronjob) nem futott le parancssorból. A következő hibák tűntek fel:",
+ "All checks passed." : "Minden ellenőrzés sikeres.",
"Open documentation" : "Dokumentáció megnyitása",
"Allow apps to use the Share API" : "Lehetővé teszi, hogy a programmodulok is használhassák a megosztást",
"Allow users to share via link" : "Engedjük meg az állományok linkekkel történő megosztását",
@@ -136,6 +140,8 @@
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "A cron.php webcron szolgáltatásként van regisztrálva, hogy 15 percenként egyszer lefuttassa a cron.php-t.",
"Use system's cron service to call the cron.php file every 15 minutes." : "A rendszer cron szolgáltatását használjuk, mely a cron.php állományt futtatja le 15 percenként.",
"Enable server-side encryption" : "Szerveroldali titkosítás engedélyezése",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "A szerveroldali titkosítás egyirányú folyamat. Ha egyszer engedélyezve lett a titkosítás, akkor onnantól kezdve a szerveren az összes fájl titkosításra kerül, melyet később nem lehet visszafordítani.",
+ "This is the final warning: Do you really want to enable encryption?" : "Ez az utolsó figyelmeztetés: Biztosan szeretnéd engedélyezni a titkosítást?",
"Enable encryption" : "Titkosítás engedélyezése",
"No encryption module loaded, please enable an encryption module in the app menu." : "Nincs titkosítási modul betöltve, kérjük engedélyezd a titkosítási modult az alkalmazások menüben.",
"Select default encryption module:" : "Alapértelmezett titkosítási modul:",
diff --git a/settings/l10n/id.js b/settings/l10n/id.js
index d0303b7b221..c36bd864138 100644
--- a/settings/l10n/id.js
+++ b/settings/l10n/id.js
@@ -132,6 +132,7 @@ OC.L10N.register(
"If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Jika instalasi Anda tidak di root domain dan menggunakan sistem cron, hal tersebut dapat menyebabkan masalah dengan pembuatan URL. Untuk mencegah masalah tersebut, mohon atur opsi \"overwrite.cli.url\" pada berkas config.php Anda ke jalur lokasi webroot instalasi Anda (Disarankan: \"%s\")",
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Tidak mungkin untuk mengeksekusi cronjob via CLI. Kesalahan teknis berikut muncul:",
"Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "Mohon periksa dua kali <a target=\"_blank\" href=\"%s\">panduan instalasi ↗</a>, dan periksa segala kesalahan atau peringatan pada <a href=\"#log-section\">log</a>.",
+ "All checks passed." : "Semua pemeriksaan lulus.",
"Open documentation" : "Buka dokumentasi",
"Allow apps to use the Share API" : "Izinkan aplikasi untuk menggunakan API Pembagian",
"Allow users to share via link" : "Izinkan pengguna untuk membagikan via tautan",
@@ -154,6 +155,12 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php didaftarkan pada layanan webcron untuk memanggil cron.php setiap 15 menit melalui http.",
"Use system's cron service to call the cron.php file every 15 minutes." : "Gunakan layanan cron sistem untuk memanggil berkas cron.php setiap 15 menit.",
"Enable server-side encryption" : "Aktifkan enkripsi sisi-server",
+ "Please read carefully before activating server-side encryption: " : "Mohon baca dengan teliti sebelum mengaktifkan enkripsi server-side:",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Enkripsi server-side adalah proses sekali jalan. Setelah enkripsi diaktifkan, semua berkas mulai saat ini dan selanjutnya akan dienkripsi pada server dan tidak mungkin untuk menonaktifkan enkripsi di lain waktu",
+ "Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "Siapa saja yang memiliki hak akses pada server ownCloud dapat mendeskripsi berkas-berkas Anda dengan mencegat permintaan atau membaca sandi pengguna yang disimpan dalam berkas-berkas sesi teks biasa. Enkripsi server-side tidak serta merta melindungi dari administrator jahat tetapi akan berguna untuk melindungi data Anda pada penyimpanan eksternal.",
+ "Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "Tergantung pada modul enkripsi yang sebenarnya, pada umumnya ukuran berkas akan bertambah (sekitar 35%% atau lebih ketika menggunakan modul standar)",
+ "You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "Anda disarankan mencadangkan semua kunci enkripsi Anda secara berkala untuk mencegah kehilangan data pemanen (data/<user>/files_encryption dan data/files_encryption)",
+ "This is the final warning: Do you really want to enable encryption?" : "Ini adalah peringatan terakhir: Apakah Anda yakin ingin mengaktifkan enkripsi?",
"Enable encryption" : "Aktifkan enkripsi",
"No encryption module loaded, please enable an encryption module in the app menu." : "Tidak ada modul enkripsi yang dimuat, mohon aktifkan modul enkripsi di menu aplikasi.",
"Select default encryption module:" : "Pilih modul enkripsi baku:",
diff --git a/settings/l10n/id.json b/settings/l10n/id.json
index 11d6c52359c..5f6e21dd843 100644
--- a/settings/l10n/id.json
+++ b/settings/l10n/id.json
@@ -130,6 +130,7 @@
"If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Jika instalasi Anda tidak di root domain dan menggunakan sistem cron, hal tersebut dapat menyebabkan masalah dengan pembuatan URL. Untuk mencegah masalah tersebut, mohon atur opsi \"overwrite.cli.url\" pada berkas config.php Anda ke jalur lokasi webroot instalasi Anda (Disarankan: \"%s\")",
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Tidak mungkin untuk mengeksekusi cronjob via CLI. Kesalahan teknis berikut muncul:",
"Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "Mohon periksa dua kali <a target=\"_blank\" href=\"%s\">panduan instalasi ↗</a>, dan periksa segala kesalahan atau peringatan pada <a href=\"#log-section\">log</a>.",
+ "All checks passed." : "Semua pemeriksaan lulus.",
"Open documentation" : "Buka dokumentasi",
"Allow apps to use the Share API" : "Izinkan aplikasi untuk menggunakan API Pembagian",
"Allow users to share via link" : "Izinkan pengguna untuk membagikan via tautan",
@@ -152,6 +153,12 @@
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php didaftarkan pada layanan webcron untuk memanggil cron.php setiap 15 menit melalui http.",
"Use system's cron service to call the cron.php file every 15 minutes." : "Gunakan layanan cron sistem untuk memanggil berkas cron.php setiap 15 menit.",
"Enable server-side encryption" : "Aktifkan enkripsi sisi-server",
+ "Please read carefully before activating server-side encryption: " : "Mohon baca dengan teliti sebelum mengaktifkan enkripsi server-side:",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Enkripsi server-side adalah proses sekali jalan. Setelah enkripsi diaktifkan, semua berkas mulai saat ini dan selanjutnya akan dienkripsi pada server dan tidak mungkin untuk menonaktifkan enkripsi di lain waktu",
+ "Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "Siapa saja yang memiliki hak akses pada server ownCloud dapat mendeskripsi berkas-berkas Anda dengan mencegat permintaan atau membaca sandi pengguna yang disimpan dalam berkas-berkas sesi teks biasa. Enkripsi server-side tidak serta merta melindungi dari administrator jahat tetapi akan berguna untuk melindungi data Anda pada penyimpanan eksternal.",
+ "Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "Tergantung pada modul enkripsi yang sebenarnya, pada umumnya ukuran berkas akan bertambah (sekitar 35%% atau lebih ketika menggunakan modul standar)",
+ "You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "Anda disarankan mencadangkan semua kunci enkripsi Anda secara berkala untuk mencegah kehilangan data pemanen (data/<user>/files_encryption dan data/files_encryption)",
+ "This is the final warning: Do you really want to enable encryption?" : "Ini adalah peringatan terakhir: Apakah Anda yakin ingin mengaktifkan enkripsi?",
"Enable encryption" : "Aktifkan enkripsi",
"No encryption module loaded, please enable an encryption module in the app menu." : "Tidak ada modul enkripsi yang dimuat, mohon aktifkan modul enkripsi di menu aplikasi.",
"Select default encryption module:" : "Pilih modul enkripsi baku:",
diff --git a/settings/l10n/it.js b/settings/l10n/it.js
index 55493ffbcd6..5316867a882 100644
--- a/settings/l10n/it.js
+++ b/settings/l10n/it.js
@@ -256,7 +256,7 @@ OC.L10N.register(
"Issued By" : "Emesso da",
"Valid until %s" : "Valido fino al %s",
"Import root certificate" : "Importa certificato radice",
- "Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}." : "Sviluppato dalla {communityopen}comunità di ownCloud{linkclose}, il {githubopen}codice sorgente{linkclose} è licenziato nei termini della {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}.",
+ "Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}." : "Sviluppato dalla {communityopen}comunità di ownCloud{linkclose}, il {githubopen}codice sorgente{linkclose} è rilasciato nei termini della licenza {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}.",
"Show storage location" : "Mostra posizione di archiviazione",
"Show last log in" : "Mostra ultimo accesso",
"Show user backend" : "Mostra il motore utente",
diff --git a/settings/l10n/it.json b/settings/l10n/it.json
index a3dd09a0b4b..c13d21bf4b7 100644
--- a/settings/l10n/it.json
+++ b/settings/l10n/it.json
@@ -254,7 +254,7 @@
"Issued By" : "Emesso da",
"Valid until %s" : "Valido fino al %s",
"Import root certificate" : "Importa certificato radice",
- "Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}." : "Sviluppato dalla {communityopen}comunità di ownCloud{linkclose}, il {githubopen}codice sorgente{linkclose} è licenziato nei termini della {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}.",
+ "Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}." : "Sviluppato dalla {communityopen}comunità di ownCloud{linkclose}, il {githubopen}codice sorgente{linkclose} è rilasciato nei termini della licenza {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}.",
"Show storage location" : "Mostra posizione di archiviazione",
"Show last log in" : "Mostra ultimo accesso",
"Show user backend" : "Mostra il motore utente",
diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js
index 889b2c31d99..89395920948 100644
--- a/settings/l10n/tr.js
+++ b/settings/l10n/tr.js
@@ -10,6 +10,7 @@ OC.L10N.register(
"Cron" : "Cron",
"Email server" : "E-posta sunucusu",
"Log" : "Günlük",
+ "Server status" : "Sunucu durumu",
"Tips & tricks" : "İpuçları ve hileler",
"Updates" : "Güncellemeler",
"Authentication error" : "Kimlik doğrulama hatası",
@@ -30,7 +31,9 @@ OC.L10N.register(
"Unable to change password" : "Parola değiştirilemiyor",
"Enabled" : "Etkin",
"Not enabled" : "Etkin değil",
+ "installing and updating apps via the app store or Federated Cloud Sharing" : "uygulama mağazası ve Birleşmiş Bulut Paylaşımından uygulama kurma ve güncelleme",
"Federated Cloud Sharing" : "Birleşmiş Bulut Paylaşımı",
+ "cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL eskide kalmış bir sürüm %s kullanıyor (%s). Lütfen işletim sisteminizi güncelleyin yoksa %s gibi özellikler düzgün çalışmayacaktır.",
"A problem occurred, please check your log files (Error: %s)" : "Bir problem oluştu, lütfen log dosyalarını kontrol edin (Hata: %s)",
"Migration Completed" : "Taşınma Tamamlandı",
"Group already exists." : "Grup zaten mevcut.",
@@ -75,6 +78,7 @@ OC.L10N.register(
"Uninstalling ...." : "Kaldırılıyor ....",
"Error while uninstalling app" : "Uygulama kaldırılırken hata",
"Uninstall" : "Kaldır",
+ "An error occurred: {message}" : "Bir hata oluştu: {message}",
"Select a profile picture" : "Bir profil fotoğrafı seçin",
"Very weak password" : "Çok güçsüz parola",
"Weak password" : "Güçsüz parola",
@@ -128,6 +132,7 @@ OC.L10N.register(
"If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Eğer kurulumunuz alan adının köküne yapılmamışsa ve sistem cron'u kullanıyorsa, URL oluşturma ile ilgili sorunlar oluşabilir. Bu sorunların önüne geçmek için, kurulumunuzun web kök yolundaki config.php dosyasında \"overwrite.cli.url\" seçeneğini ayarlayın (Önerilen: \"%s\")",
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Bu CLI ile cronjobı çalıştırmak mümkün değildi. Aşağıdaki teknik hatalar ortaya çıkmıştır:",
"Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "Lütfen <a target=\"_blank\" href=\"%s\">kurulum rehberlerini ↗</a> iki kez denetleyip <a href=\"#log-section\">günlük</a> içerisindeki hata ve uyarılara bakın.",
+ "All checks passed." : "Tüm kontroller geçildi.",
"Open documentation" : "Belgelendirmeyi aç",
"Allow apps to use the Share API" : "Uygulamaların paylaşım API'sini kullanmasına izin ver",
"Allow users to share via link" : "Kullanıcıların bağlantı ile paylaşmasına izin ver",
@@ -150,6 +155,12 @@ OC.L10N.register(
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php, http üzerinden her 15 dakikada bir çağrılması için webcron hizmetine kaydedilir.",
"Use system's cron service to call the cron.php file every 15 minutes." : "Cron.php dosyasını her 15 dakikada bir çağırmak için sistem cron hizmetini kullan.",
"Enable server-side encryption" : "Sunucu taraflı şifrelemeyi aç",
+ "Please read carefully before activating server-side encryption: " : "Lütfen sunucu tarafında şifrelemeyi etkinleştirmeden önce dikkatlice okuyun: ",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Sunucu tarafında şifreleme tek yönlü bir işlemdir. Bir defa etkinleştirildiğinde sunucudaki tüm dosyalar şifrelenir ve ileri bir tarihte şifrelemeyi iptal etmek mümkün değildir",
+ "Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "ownCloud sunucunuza erişimi olan biri isteklere müdahale ederek veya oturum dosyalarında düz metin olarak saklanan parolayı kullanarak dosyalarınızın şifrelenmesini çözebilir. Bu nedenle sunucu tarafında şifreleme işlemi kötü niyetli sistem yöneticisine karşı koruma sağlamaz ama verinizi harici depolamada tutmanız durumunda yararlıdır.",
+ "Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "Gerçek şifreleme modülüne bağlı olarak genel dosya boyutu artar (35%% veya varsayılan modül kullanıldığında daha fazla)",
+ "You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "Veri kaybının önüne geçmek için düzenli olarak tüm şifreleme anahtarlarınızı yedeklemelisiniz (data/<user>/files_encryption and data/files_encryption)",
+ "This is the final warning: Do you really want to enable encryption?" : "Bu son uyarıdır: Şifrelemeyi etkinleştirmek istiyor musunuz?",
"Enable encryption" : "Şifrelemeyi aç",
"No encryption module loaded, please enable an encryption module in the app menu." : "Hiç şifrelenme modülü yüklenmemiş, lütfen uygulama menüsünden bir şifreleme modülü etkinleştirin.",
"Select default encryption module:" : "Öntanımlı şifreleme modülünü seçin:",
@@ -195,6 +206,7 @@ OC.L10N.register(
"licensed" : "lisanslı",
"Documentation:" : "Belgelendirme:",
"User documentation" : "Kullanıcı belgelendirmesi",
+ "Admin documentation" : "Yönetici belgelendirmesi",
"Show description …" : "Açıklamayı göster...",
"Hide description …" : "Açıklamayı gizle...",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Bu uygulama, aşağıdaki bağımlılıklar sağlanmadığından yüklenemiyor:",
@@ -233,6 +245,7 @@ OC.L10N.register(
"Upload new" : "Yeni yükle",
"Select new from Files" : "Dosyalardan seç",
"Remove image" : "Resmi kaldır",
+ "Either png or jpg. Ideally square but you will be able to crop it. The file is not allowed to exceed the maximum size of 20 MB." : "Png veya jpg'den biri olmalıdır. İdeal olanı karedir ama kırpmanıza izin verilecektir. Dosya boyutu 20MB'ı geçemez.",
"Your avatar is provided by your original account." : "Görüntü resminiz, özgün hesabınız tarafından sağlanıyor.",
"Cancel" : "İptal",
"Choose as profile image" : "Profil resmi olarak seç",
diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json
index d4cc45eff69..51ec1a007e0 100644
--- a/settings/l10n/tr.json
+++ b/settings/l10n/tr.json
@@ -8,6 +8,7 @@
"Cron" : "Cron",
"Email server" : "E-posta sunucusu",
"Log" : "Günlük",
+ "Server status" : "Sunucu durumu",
"Tips & tricks" : "İpuçları ve hileler",
"Updates" : "Güncellemeler",
"Authentication error" : "Kimlik doğrulama hatası",
@@ -28,7 +29,9 @@
"Unable to change password" : "Parola değiştirilemiyor",
"Enabled" : "Etkin",
"Not enabled" : "Etkin değil",
+ "installing and updating apps via the app store or Federated Cloud Sharing" : "uygulama mağazası ve Birleşmiş Bulut Paylaşımından uygulama kurma ve güncelleme",
"Federated Cloud Sharing" : "Birleşmiş Bulut Paylaşımı",
+ "cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL eskide kalmış bir sürüm %s kullanıyor (%s). Lütfen işletim sisteminizi güncelleyin yoksa %s gibi özellikler düzgün çalışmayacaktır.",
"A problem occurred, please check your log files (Error: %s)" : "Bir problem oluştu, lütfen log dosyalarını kontrol edin (Hata: %s)",
"Migration Completed" : "Taşınma Tamamlandı",
"Group already exists." : "Grup zaten mevcut.",
@@ -73,6 +76,7 @@
"Uninstalling ...." : "Kaldırılıyor ....",
"Error while uninstalling app" : "Uygulama kaldırılırken hata",
"Uninstall" : "Kaldır",
+ "An error occurred: {message}" : "Bir hata oluştu: {message}",
"Select a profile picture" : "Bir profil fotoğrafı seçin",
"Very weak password" : "Çok güçsüz parola",
"Weak password" : "Güçsüz parola",
@@ -126,6 +130,7 @@
"If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "Eğer kurulumunuz alan adının köküne yapılmamışsa ve sistem cron'u kullanıyorsa, URL oluşturma ile ilgili sorunlar oluşabilir. Bu sorunların önüne geçmek için, kurulumunuzun web kök yolundaki config.php dosyasında \"overwrite.cli.url\" seçeneğini ayarlayın (Önerilen: \"%s\")",
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Bu CLI ile cronjobı çalıştırmak mümkün değildi. Aşağıdaki teknik hatalar ortaya çıkmıştır:",
"Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "Lütfen <a target=\"_blank\" href=\"%s\">kurulum rehberlerini ↗</a> iki kez denetleyip <a href=\"#log-section\">günlük</a> içerisindeki hata ve uyarılara bakın.",
+ "All checks passed." : "Tüm kontroller geçildi.",
"Open documentation" : "Belgelendirmeyi aç",
"Allow apps to use the Share API" : "Uygulamaların paylaşım API'sini kullanmasına izin ver",
"Allow users to share via link" : "Kullanıcıların bağlantı ile paylaşmasına izin ver",
@@ -148,6 +153,12 @@
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php, http üzerinden her 15 dakikada bir çağrılması için webcron hizmetine kaydedilir.",
"Use system's cron service to call the cron.php file every 15 minutes." : "Cron.php dosyasını her 15 dakikada bir çağırmak için sistem cron hizmetini kullan.",
"Enable server-side encryption" : "Sunucu taraflı şifrelemeyi aç",
+ "Please read carefully before activating server-side encryption: " : "Lütfen sunucu tarafında şifrelemeyi etkinleştirmeden önce dikkatlice okuyun: ",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Sunucu tarafında şifreleme tek yönlü bir işlemdir. Bir defa etkinleştirildiğinde sunucudaki tüm dosyalar şifrelenir ve ileri bir tarihte şifrelemeyi iptal etmek mümkün değildir",
+ "Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "ownCloud sunucunuza erişimi olan biri isteklere müdahale ederek veya oturum dosyalarında düz metin olarak saklanan parolayı kullanarak dosyalarınızın şifrelenmesini çözebilir. Bu nedenle sunucu tarafında şifreleme işlemi kötü niyetli sistem yöneticisine karşı koruma sağlamaz ama verinizi harici depolamada tutmanız durumunda yararlıdır.",
+ "Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "Gerçek şifreleme modülüne bağlı olarak genel dosya boyutu artar (35%% veya varsayılan modül kullanıldığında daha fazla)",
+ "You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "Veri kaybının önüne geçmek için düzenli olarak tüm şifreleme anahtarlarınızı yedeklemelisiniz (data/<user>/files_encryption and data/files_encryption)",
+ "This is the final warning: Do you really want to enable encryption?" : "Bu son uyarıdır: Şifrelemeyi etkinleştirmek istiyor musunuz?",
"Enable encryption" : "Şifrelemeyi aç",
"No encryption module loaded, please enable an encryption module in the app menu." : "Hiç şifrelenme modülü yüklenmemiş, lütfen uygulama menüsünden bir şifreleme modülü etkinleştirin.",
"Select default encryption module:" : "Öntanımlı şifreleme modülünü seçin:",
@@ -193,6 +204,7 @@
"licensed" : "lisanslı",
"Documentation:" : "Belgelendirme:",
"User documentation" : "Kullanıcı belgelendirmesi",
+ "Admin documentation" : "Yönetici belgelendirmesi",
"Show description …" : "Açıklamayı göster...",
"Hide description …" : "Açıklamayı gizle...",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Bu uygulama, aşağıdaki bağımlılıklar sağlanmadığından yüklenemiyor:",
@@ -231,6 +243,7 @@
"Upload new" : "Yeni yükle",
"Select new from Files" : "Dosyalardan seç",
"Remove image" : "Resmi kaldır",
+ "Either png or jpg. Ideally square but you will be able to crop it. The file is not allowed to exceed the maximum size of 20 MB." : "Png veya jpg'den biri olmalıdır. İdeal olanı karedir ama kırpmanıza izin verilecektir. Dosya boyutu 20MB'ı geçemez.",
"Your avatar is provided by your original account." : "Görüntü resminiz, özgün hesabınız tarafından sağlanıyor.",
"Cancel" : "İptal",
"Choose as profile image" : "Profil resmi olarak seç",
diff --git a/settings/l10n/zh_CN.js b/settings/l10n/zh_CN.js
index 36835692c25..6b6d50dccb2 100644
--- a/settings/l10n/zh_CN.js
+++ b/settings/l10n/zh_CN.js
@@ -3,12 +3,14 @@ OC.L10N.register(
{
"APCu" : "APCu",
"Redis" : "Redis",
+ "Security & setup warnings" : "安全 & 设置警告",
"Sharing" : "共享",
"Server-side encryption" : "服务器端加密",
"External Storage" : "外部存储",
"Cron" : "计划任务",
"Email server" : "电子邮件服务器",
"Log" : "日志",
+ "Server status" : "服务器状态",
"Tips & tricks" : "技巧提示",
"Updates" : "更新",
"Authentication error" : "认证错误",
@@ -25,20 +27,45 @@ OC.L10N.register(
"No user supplied" : "没有满足的用户",
"Please provide an admin recovery password, otherwise all user data will be lost" : "请提供管理员恢复密码,否则所有用户的数据都将遗失。",
"Wrong admin recovery password. Please check the password and try again." : "错误的管理员恢复密码。请检查密码并重试。",
+ "Backend doesn't support password change, but the user's encryption key was successfully updated." : "后端不支持密码更改,但用户的加密密钥已成功更新。",
"Unable to change password" : "不能更改密码",
"Enabled" : "开启",
"Not enabled" : "未启用",
+ "installing and updating apps via the app store or Federated Cloud Sharing" : "通过应用程序商店或联合云共享安装和更新应用程序",
"Federated Cloud Sharing" : "联合云共享",
+ "cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL使用了过时 %s 版本 (%s)。请更新你的操作系统或功能比如 %s 将无法可靠地工作。",
+ "A problem occurred, please check your log files (Error: %s)" : "出现了故障,请检查你的日志文件 (错误: %s)",
"Migration Completed" : "迁移完成",
+ "Group already exists." : "组已经存在。",
+ "Unable to add group." : "无法添加组。",
+ "Unable to delete group." : "无法删除组",
+ "log-level out of allowed range" : "日志级别超出允许的范围",
"Saved" : "已保存",
"test email settings" : "测试电子邮件设置",
+ "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "在发送电子邮件时出现问题。请修改您的设置。 (错误: %s)",
"Email sent" : "邮件已发送",
"You need to set your user email before being able to send test emails." : "在发送测试邮件前您需要设置您的用户电子邮件。",
+ "Invalid mail address" : "无效的电子邮件地址",
+ "A user with that name already exists." : "使用该名称的用户已存在。",
+ "Unable to create user." : "无法创建用户。",
+ "Your %s account was created" : "你的帐户 %s 已创建",
+ "Unable to delete user." : "不能删除用户",
+ "Forbidden" : "被禁止",
+ "Invalid user" : "用户无效",
+ "Unable to change mail address" : "无法更改邮箱地址",
"Email saved" : "电子邮件已保存",
"Are you really sure you want add \"{domain}\" as trusted domain?" : "你真的希望添加 \"{domain}\" 为信任域?",
"Add trusted domain" : "添加信任域",
+ "Migration in progress. Please wait until the migration is finished" : "迁移正在进行中。请等待,直到完成迁移",
+ "Migration started …" : "迁移开始...",
"Sending..." : "正在发送...",
+ "Official" : "官方",
+ "Approved" : "已认可",
+ "Experimental" : "实验",
"All" : "全部",
+ "Official apps are developed by and within the ownCloud community. They offer functionality central to ownCloud and are ready for production use." : "官方应用是由 ownCloud 社区开发。他们提供 ownCloud 的功能核心并准备用于生产。",
+ "Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "已认可的应用是由值得信赖的开发商开发,并已通过了一个粗略的安全检查。他们放在一个开放的代码库并且维护人员认为他们是稳定的差不多可以正常使用。",
+ "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "此应用未检查安全问题,它是新的或已知是不稳定的。安装风险自担。",
"Update to %s" : "更新为 %s",
"Please wait...." : "请稍等....",
"Error while disabling app" : "禁用 app 时出错",
@@ -51,6 +78,7 @@ OC.L10N.register(
"Uninstalling ...." : "卸载中....",
"Error while uninstalling app" : "卸载应用时发生了一个错误",
"Uninstall" : "卸载",
+ "An error occurred: {message}" : "发生错误: {message}",
"Select a profile picture" : "选择头像",
"Very weak password" : "非常弱的密码",
"Weak password" : "弱密码",
@@ -59,18 +87,22 @@ OC.L10N.register(
"Strong password" : "强密码",
"Valid until {date}" : "有效期至 {date}",
"Delete" : "删除",
+ "An error occurred. Please upload an ASCII-encoded PEM certificate." : "出现了一个错误。请上传 ASCII 编码的 PEM 证书。",
"Groups" : "组",
"Unable to delete {objName}" : "无法删除 {objName}",
"Error creating group" : "创建组时出错",
"A valid group name must be provided" : "请提供一个有效的组名称",
"deleted {groupName}" : "已删除 {groupName}",
"undo" : "撤销",
+ "no group" : "没有组",
"never" : "从不",
"deleted {userName}" : "已删除 {userName}",
"add group" : "增加组",
+ "Changing the password will result in data loss, because data recovery is not available for this user" : "更改密码会导致数据丢失,因为数据恢复不适用于此用户",
"A valid username must be provided" : "必须提供合法的用户名",
"Error creating user" : "创建用户出错",
"A valid password must be provided" : "必须提供合法的密码",
+ "A valid email must be provided" : "必须提供合法的用户名",
"__language_name__" : "简体中文",
"Sync clients" : "客户端",
"Personal info" : "个人信息",
@@ -86,11 +118,21 @@ OC.L10N.register(
"NT LAN Manager" : "NT LAN 管理器",
"SSL" : "SSL",
"TLS" : "TLS",
+ "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "PHP 似乎没有设置好查询的系统环境变量。 用 getenv(\\\"PATH\\\") 测试只返回一个空值。",
+ "Please check the installation documentation for php configuration notes and the php configuration of your server, especially when using php-fpm." : "请检查PHP配置说明和服务器的 PHP 配置的安装文档,使用 PHP-FPM 时尤其如此。",
+ "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "只读配置已启用。这样可防止通过 WEB 接口设置一些配置。此外,每次更新后该文件需要手动设置为可写。",
"PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "PHP 被设置为移除行内 <doc> 块,这将导致数个核心应用无法访问。",
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "这可能是由缓存/加速器造成的,例如 Zend OPcache 或 eAccelerator。",
+ "Your server is running on Microsoft Windows. We highly recommend Linux for optimal user experience." : "你的服务器是运行于 Microsoft Windows 系统。我们强烈推荐使用 Linux 系统以获得最佳的用户体验。比如中文文件夹和文件名支持。",
+ "%1$s below version %2$s is installed, for stability and performance reasons we recommend to update to a newer %1$s version." : "%1$s 下版本 %2$s 已安装。基于稳定和性能的原因,我们强烈建议更新至 %1$s 版本。",
"The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "PHP模块'文件信息'丢失. 我们强烈建议启用此模块以便mime类型检测取得最佳结果.",
"System locale can not be set to a one which supports UTF-8." : "系统语系无法设置为支持 UTF-8 的语系。",
"This means that there might be problems with certain characters in file names." : "这意味着一些文件名中的特定字符可能有问题。",
+ "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "我们强烈建议安装在系统上所需的软件包支持以下区域设置之一: %s.",
+ "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "如果你不是安装在网域根目录而且又使用系统定时计划任务,那么可以导致 URL 链接生成问题。为了避免这些问题,请在你的 Config.php 文件中设置 \\\"overwrite.cli.url\\\" 选项为 webroot 安装根目录 (建议: \\\"%s\\\")",
+ "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "由于下面的错误,无法通过 CLI 执行定时计划任务:",
+ "Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "请点击检查 <a target=\\\"_blank\\\" href=\\\"%s\\\"> 安装向导 ↗</a>, 点击 <a href=\\\"#log-section\\\"> 日志 </a>查看详细错误和警告。",
+ "All checks passed." : "所有检查已通过。",
"Open documentation" : "打开文档",
"Allow apps to use the Share API" : "允许应用软件使用共享API",
"Allow users to share via link" : "允许用户通过链接分享文件",
@@ -106,12 +148,25 @@ OC.L10N.register(
"Allow users to send mail notification for shared files to other users" : "允许用户发送共享文件的邮件通知给其他用户",
"Exclude groups from sharing" : "在分享中排除组",
"These groups will still be able to receive shares, but not to initiate them." : "这些组将仍可以获取分享,但无法向他人分享。",
+ "Last cron job execution: %s." : "上次定时任务执行于: %s.",
+ "Last cron job execution: %s. Something seems wrong." : "上次定时任务执行于: %s. 似乎有些问题。",
"Cron was not executed yet!" : "定时任务还未被执行!",
"Execute one task with each page loaded" : "每个页面加载后执行一个任务",
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php 已注册于一个 webcron 服务来通过 http 每 15 分钟执行 cron.php。",
"Use system's cron service to call the cron.php file every 15 minutes." : "使用系统 CRON 服务每 15 分钟执行一次 cron.php 文件。",
"Enable server-side encryption" : "启用服务器端加密",
+ "Please read carefully before activating server-side encryption: " : "在激活服务器端加密之前,请仔细阅读:",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "服务器端加密是一个单向的过程。一旦启用加密,从该点向前所有文件都将在服务器上进行加密,它将无法在以后禁用加密",
+ "Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "只要有权访问您的 ownCloud 服务器就可能解密你的文件,通过截获请求或读出以纯文本会话文件存储的用户密码。服务端加密。它不仅让你免遭恶意的管理员查看隐私,在保护你在外部托管的存储中的数据也非常有用。",
+ "Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "根据实际加密模块上的一般文件大小而增加 (使用默认的模块时,35%% 以上)",
+ "You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "你应该定期备份所有加密密钥,以防数据永久丢失 (data/<user>/files_encryption 和 data/files_encryption)",
+ "This is the final warning: Do you really want to enable encryption?" : "这是最后一次警告:你真的想启用加密?",
"Enable encryption" : "启用加密",
+ "No encryption module loaded, please enable an encryption module in the app menu." : "没有加载加密模块,请在 APP 应用菜单中启用加密模块。",
+ "Select default encryption module:" : "选择默认的加密模块:",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "你需要升级你的加密密钥 (旧版 ownCloud <= 8.0) 。 请在应用中启用 \\\"Default encryption module\\\" 并运行 'occ encryption:migrate'",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "您需要将加密密钥从旧版(ownCloud<=8.0)迁移到新版。",
+ "Start migration" : "开始迁移",
"This is used for sending out notifications." : "这被用于发送通知。",
"Send mode" : "发送模式",
"Encryption" : "加密",
@@ -124,26 +179,49 @@ OC.L10N.register(
"Credentials" : "凭证",
"SMTP Username" : "SMTP 用户名",
"SMTP Password" : "SMTP 密码",
+ "Store credentials" : "存储凭据",
"Test email settings" : "测试电子邮件设置",
"Send email" : "发送邮件",
"Log level" : "日志级别",
+ "Download logfile" : "下载日志文件",
"More" : "更多",
"Less" : "更少",
+ "The logfile is bigger than 100 MB. Downloading it may take some time!" : "日志文件超过 100 MB。下载可能需要一些时间!",
+ "Transactional File Locking is enabled." : "事务文件锁定已启用。",
+ "Transactional File Locking is disabled." : "事务文件锁定已禁用。",
+ "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite 被用作数据库。对于较大数据量的安装和使用,我们建议您切换到不同的数据库后端。",
"Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "特别当使用桌面客户端来同步文件时,不鼓励使用 SQLite 。",
+ "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" href=\"%s\">documentation ↗</a>." : "要迁移到另一个数据库请使用命令行工具: 'occ db:convert-type', 或者查看 <a target=\\\"_blank\\\" href=\\\"%s\\\"> 相关文档 ↗</a>.",
+ "How to do backups" : "如何做备份",
"Advanced monitoring" : "高级监控",
"Performance tuning" : "性能优化",
"Improving the config.php" : "正在优化 config.php",
"Theming" : "主题",
+ "Hardening and security guidance" : "强化和安全指南",
"Version" : "版本",
+ "Developer documentation" : "开发者文档",
+ "Experimental applications ahead" : "未来的实验应用",
+ "Experimental apps are not checked for security issues, new or known to be unstable and under heavy development. Installing them can cause data loss or security breaches." : "实验应用程序没有在安全性的问题上作过多检查,新的或已知的不稳定 BUG 都在开发中。安装它们可能会导致数据丢失或安全漏洞。",
"by" : "被",
+ "licensed" : "许可",
"Documentation:" : "文档:",
"User documentation" : "用户文档",
+ "Admin documentation" : "管理员文档",
+ "Show description …" : "显示描述...",
+ "Hide description …" : "隐藏描述...",
+ "This app cannot be installed because the following dependencies are not fulfilled:" : "此应用程序无法安装,因为以下依赖性不满足:",
"Enable only for specific groups" : "仅对特定的组开放",
"Uninstall App" : "卸载应用",
+ "Enable experimental apps" : "启用实验性应用程序",
+ "No apps found for your version" : "未找到适合当前版本的应用",
+ "Hey there,<br><br>just letting you know that you now have an %s account.<br><br>Your username: %s<br>Access it: <a href=\"%s\">%s</a><br><br>" : "亲,<br><br>现在我们为你开通了 %s 私有云帐户。<br><br>你的用户名: %s<br>访问网址: <a href=\\\"%s\\\">%s</a><br><br>",
"Cheers!" : "干杯!",
+ "Hey there,\n\njust letting you know that you now have an %s account.\n\nYour username: %s\nAccess it: %s\n\n" : "亲,\\n\\n 现在我们为你开通了 %s 私有去帐户。\\n\\n 你的用户名: %s\\n 访问网址: %s\\n 你的初始密码需要咨询系统管理员。或者你也可以在登录页面输入任意密码登录,\\n登录窗口将出现忘记密码链接,点击通过注册邮箱重设初始密码。\\n\\n",
"Administrator documentation" : "管理员文档",
"Online documentation" : "在线文档",
"Forum" : "论坛",
+ "Issue tracker" : "问题跟踪",
+ "Commercial support" : "商业支持",
"Get the apps to sync your files" : "安装应用进行文件同步",
"Desktop client" : "桌面客户端",
"Android app" : "Android 应用",
@@ -156,13 +234,18 @@ OC.L10N.register(
"Current password" : "当前密码",
"New password" : "新密码",
"Change password" : "修改密码",
+ "Full name" : "全名",
+ "No display name set" : "不显示名称设置",
"Email" : "电子邮件",
"Your email address" : "您的电子邮件",
"Fill in an email address to enable password recovery and receive notifications" : "填入电子邮件地址从而启用密码恢复和接收通知",
+ "No email address set" : "尚未设置 Email 地址",
+ "You are member of the following groups:" : "您是以下组的成员:",
"Profile picture" : "联系人图片",
"Upload new" : "上传新的",
"Select new from Files" : "从文件中选择一个新的",
"Remove image" : "移除图片",
+ "Either png or jpg. Ideally square but you will be able to crop it. The file is not allowed to exceed the maximum size of 20 MB." : "png 或 jpg。正方形比较理想但你也可以之后对其进行裁剪。文件大小最大不允许超过 20MB。",
"Your avatar is provided by your original account." : "您的头像由您的原始账户所提供。",
"Cancel" : "取消",
"Choose as profile image" : "用作头像",
@@ -172,10 +255,15 @@ OC.L10N.register(
"Valid until" : "有效期至",
"Issued By" : "授权由",
"Valid until %s" : "有效期至 %s",
+ "Import root certificate" : "导入根证书",
"Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}." : "由 {communityopen}ownCloud 社区{linkclose}开发,{githubopen}源代码{linkclose}在 {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr> 许可证{linkclose}下发布。",
"Show storage location" : "显示存储位置",
"Show last log in" : "显示最后登录",
+ "Show user backend" : "显示用户后端",
+ "Send email to new user" : "发送电子邮件给新用户",
+ "Show email address" : "显示邮件地址",
"Username" : "用户名",
+ "E-Mail" : "E-Mail",
"Create" : "创建",
"Admin Recovery Password" : "管理恢复密码",
"Enter the recovery password in order to recover the users files during password change" : "输入恢复密码来在更改密码的时候恢复用户文件",
@@ -188,6 +276,7 @@ OC.L10N.register(
"Unlimited" : "无限",
"Other" : "其它",
"Full Name" : "全名",
+ "Group Admin for" : "设为以下组管理员",
"Quota" : "配额",
"Storage Location" : "存储空间位置",
"User Backend" : "用户后端",
diff --git a/settings/l10n/zh_CN.json b/settings/l10n/zh_CN.json
index e965deb8be7..41025e81a7d 100644
--- a/settings/l10n/zh_CN.json
+++ b/settings/l10n/zh_CN.json
@@ -1,12 +1,14 @@
{ "translations": {
"APCu" : "APCu",
"Redis" : "Redis",
+ "Security & setup warnings" : "安全 & 设置警告",
"Sharing" : "共享",
"Server-side encryption" : "服务器端加密",
"External Storage" : "外部存储",
"Cron" : "计划任务",
"Email server" : "电子邮件服务器",
"Log" : "日志",
+ "Server status" : "服务器状态",
"Tips & tricks" : "技巧提示",
"Updates" : "更新",
"Authentication error" : "认证错误",
@@ -23,20 +25,45 @@
"No user supplied" : "没有满足的用户",
"Please provide an admin recovery password, otherwise all user data will be lost" : "请提供管理员恢复密码,否则所有用户的数据都将遗失。",
"Wrong admin recovery password. Please check the password and try again." : "错误的管理员恢复密码。请检查密码并重试。",
+ "Backend doesn't support password change, but the user's encryption key was successfully updated." : "后端不支持密码更改,但用户的加密密钥已成功更新。",
"Unable to change password" : "不能更改密码",
"Enabled" : "开启",
"Not enabled" : "未启用",
+ "installing and updating apps via the app store or Federated Cloud Sharing" : "通过应用程序商店或联合云共享安装和更新应用程序",
"Federated Cloud Sharing" : "联合云共享",
+ "cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL使用了过时 %s 版本 (%s)。请更新你的操作系统或功能比如 %s 将无法可靠地工作。",
+ "A problem occurred, please check your log files (Error: %s)" : "出现了故障,请检查你的日志文件 (错误: %s)",
"Migration Completed" : "迁移完成",
+ "Group already exists." : "组已经存在。",
+ "Unable to add group." : "无法添加组。",
+ "Unable to delete group." : "无法删除组",
+ "log-level out of allowed range" : "日志级别超出允许的范围",
"Saved" : "已保存",
"test email settings" : "测试电子邮件设置",
+ "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "在发送电子邮件时出现问题。请修改您的设置。 (错误: %s)",
"Email sent" : "邮件已发送",
"You need to set your user email before being able to send test emails." : "在发送测试邮件前您需要设置您的用户电子邮件。",
+ "Invalid mail address" : "无效的电子邮件地址",
+ "A user with that name already exists." : "使用该名称的用户已存在。",
+ "Unable to create user." : "无法创建用户。",
+ "Your %s account was created" : "你的帐户 %s 已创建",
+ "Unable to delete user." : "不能删除用户",
+ "Forbidden" : "被禁止",
+ "Invalid user" : "用户无效",
+ "Unable to change mail address" : "无法更改邮箱地址",
"Email saved" : "电子邮件已保存",
"Are you really sure you want add \"{domain}\" as trusted domain?" : "你真的希望添加 \"{domain}\" 为信任域?",
"Add trusted domain" : "添加信任域",
+ "Migration in progress. Please wait until the migration is finished" : "迁移正在进行中。请等待,直到完成迁移",
+ "Migration started …" : "迁移开始...",
"Sending..." : "正在发送...",
+ "Official" : "官方",
+ "Approved" : "已认可",
+ "Experimental" : "实验",
"All" : "全部",
+ "Official apps are developed by and within the ownCloud community. They offer functionality central to ownCloud and are ready for production use." : "官方应用是由 ownCloud 社区开发。他们提供 ownCloud 的功能核心并准备用于生产。",
+ "Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "已认可的应用是由值得信赖的开发商开发,并已通过了一个粗略的安全检查。他们放在一个开放的代码库并且维护人员认为他们是稳定的差不多可以正常使用。",
+ "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "此应用未检查安全问题,它是新的或已知是不稳定的。安装风险自担。",
"Update to %s" : "更新为 %s",
"Please wait...." : "请稍等....",
"Error while disabling app" : "禁用 app 时出错",
@@ -49,6 +76,7 @@
"Uninstalling ...." : "卸载中....",
"Error while uninstalling app" : "卸载应用时发生了一个错误",
"Uninstall" : "卸载",
+ "An error occurred: {message}" : "发生错误: {message}",
"Select a profile picture" : "选择头像",
"Very weak password" : "非常弱的密码",
"Weak password" : "弱密码",
@@ -57,18 +85,22 @@
"Strong password" : "强密码",
"Valid until {date}" : "有效期至 {date}",
"Delete" : "删除",
+ "An error occurred. Please upload an ASCII-encoded PEM certificate." : "出现了一个错误。请上传 ASCII 编码的 PEM 证书。",
"Groups" : "组",
"Unable to delete {objName}" : "无法删除 {objName}",
"Error creating group" : "创建组时出错",
"A valid group name must be provided" : "请提供一个有效的组名称",
"deleted {groupName}" : "已删除 {groupName}",
"undo" : "撤销",
+ "no group" : "没有组",
"never" : "从不",
"deleted {userName}" : "已删除 {userName}",
"add group" : "增加组",
+ "Changing the password will result in data loss, because data recovery is not available for this user" : "更改密码会导致数据丢失,因为数据恢复不适用于此用户",
"A valid username must be provided" : "必须提供合法的用户名",
"Error creating user" : "创建用户出错",
"A valid password must be provided" : "必须提供合法的密码",
+ "A valid email must be provided" : "必须提供合法的用户名",
"__language_name__" : "简体中文",
"Sync clients" : "客户端",
"Personal info" : "个人信息",
@@ -84,11 +116,21 @@
"NT LAN Manager" : "NT LAN 管理器",
"SSL" : "SSL",
"TLS" : "TLS",
+ "php does not seem to be setup properly to query system environment variables. The test with getenv(\"PATH\") only returns an empty response." : "PHP 似乎没有设置好查询的系统环境变量。 用 getenv(\\\"PATH\\\") 测试只返回一个空值。",
+ "Please check the installation documentation for php configuration notes and the php configuration of your server, especially when using php-fpm." : "请检查PHP配置说明和服务器的 PHP 配置的安装文档,使用 PHP-FPM 时尤其如此。",
+ "The Read-Only config has been enabled. This prevents setting some configurations via the web-interface. Furthermore, the file needs to be made writable manually for every update." : "只读配置已启用。这样可防止通过 WEB 接口设置一些配置。此外,每次更新后该文件需要手动设置为可写。",
"PHP is apparently setup to strip inline doc blocks. This will make several core apps inaccessible." : "PHP 被设置为移除行内 <doc> 块,这将导致数个核心应用无法访问。",
"This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "这可能是由缓存/加速器造成的,例如 Zend OPcache 或 eAccelerator。",
+ "Your server is running on Microsoft Windows. We highly recommend Linux for optimal user experience." : "你的服务器是运行于 Microsoft Windows 系统。我们强烈推荐使用 Linux 系统以获得最佳的用户体验。比如中文文件夹和文件名支持。",
+ "%1$s below version %2$s is installed, for stability and performance reasons we recommend to update to a newer %1$s version." : "%1$s 下版本 %2$s 已安装。基于稳定和性能的原因,我们强烈建议更新至 %1$s 版本。",
"The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "PHP模块'文件信息'丢失. 我们强烈建议启用此模块以便mime类型检测取得最佳结果.",
"System locale can not be set to a one which supports UTF-8." : "系统语系无法设置为支持 UTF-8 的语系。",
"This means that there might be problems with certain characters in file names." : "这意味着一些文件名中的特定字符可能有问题。",
+ "We strongly suggest installing the required packages on your system to support one of the following locales: %s." : "我们强烈建议安装在系统上所需的软件包支持以下区域设置之一: %s.",
+ "If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwrite.cli.url\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" : "如果你不是安装在网域根目录而且又使用系统定时计划任务,那么可以导致 URL 链接生成问题。为了避免这些问题,请在你的 Config.php 文件中设置 \\\"overwrite.cli.url\\\" 选项为 webroot 安装根目录 (建议: \\\"%s\\\")",
+ "It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "由于下面的错误,无法通过 CLI 执行定时计划任务:",
+ "Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "请点击检查 <a target=\\\"_blank\\\" href=\\\"%s\\\"> 安装向导 ↗</a>, 点击 <a href=\\\"#log-section\\\"> 日志 </a>查看详细错误和警告。",
+ "All checks passed." : "所有检查已通过。",
"Open documentation" : "打开文档",
"Allow apps to use the Share API" : "允许应用软件使用共享API",
"Allow users to share via link" : "允许用户通过链接分享文件",
@@ -104,12 +146,25 @@
"Allow users to send mail notification for shared files to other users" : "允许用户发送共享文件的邮件通知给其他用户",
"Exclude groups from sharing" : "在分享中排除组",
"These groups will still be able to receive shares, but not to initiate them." : "这些组将仍可以获取分享,但无法向他人分享。",
+ "Last cron job execution: %s." : "上次定时任务执行于: %s.",
+ "Last cron job execution: %s. Something seems wrong." : "上次定时任务执行于: %s. 似乎有些问题。",
"Cron was not executed yet!" : "定时任务还未被执行!",
"Execute one task with each page loaded" : "每个页面加载后执行一个任务",
"cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php 已注册于一个 webcron 服务来通过 http 每 15 分钟执行 cron.php。",
"Use system's cron service to call the cron.php file every 15 minutes." : "使用系统 CRON 服务每 15 分钟执行一次 cron.php 文件。",
"Enable server-side encryption" : "启用服务器端加密",
+ "Please read carefully before activating server-side encryption: " : "在激活服务器端加密之前,请仔细阅读:",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "服务器端加密是一个单向的过程。一旦启用加密,从该点向前所有文件都将在服务器上进行加密,它将无法在以后禁用加密",
+ "Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "只要有权访问您的 ownCloud 服务器就可能解密你的文件,通过截获请求或读出以纯文本会话文件存储的用户密码。服务端加密。它不仅让你免遭恶意的管理员查看隐私,在保护你在外部托管的存储中的数据也非常有用。",
+ "Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "根据实际加密模块上的一般文件大小而增加 (使用默认的模块时,35%% 以上)",
+ "You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "你应该定期备份所有加密密钥,以防数据永久丢失 (data/<user>/files_encryption 和 data/files_encryption)",
+ "This is the final warning: Do you really want to enable encryption?" : "这是最后一次警告:你真的想启用加密?",
"Enable encryption" : "启用加密",
+ "No encryption module loaded, please enable an encryption module in the app menu." : "没有加载加密模块,请在 APP 应用菜单中启用加密模块。",
+ "Select default encryption module:" : "选择默认的加密模块:",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "你需要升级你的加密密钥 (旧版 ownCloud <= 8.0) 。 请在应用中启用 \\\"Default encryption module\\\" 并运行 'occ encryption:migrate'",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "您需要将加密密钥从旧版(ownCloud<=8.0)迁移到新版。",
+ "Start migration" : "开始迁移",
"This is used for sending out notifications." : "这被用于发送通知。",
"Send mode" : "发送模式",
"Encryption" : "加密",
@@ -122,26 +177,49 @@
"Credentials" : "凭证",
"SMTP Username" : "SMTP 用户名",
"SMTP Password" : "SMTP 密码",
+ "Store credentials" : "存储凭据",
"Test email settings" : "测试电子邮件设置",
"Send email" : "发送邮件",
"Log level" : "日志级别",
+ "Download logfile" : "下载日志文件",
"More" : "更多",
"Less" : "更少",
+ "The logfile is bigger than 100 MB. Downloading it may take some time!" : "日志文件超过 100 MB。下载可能需要一些时间!",
+ "Transactional File Locking is enabled." : "事务文件锁定已启用。",
+ "Transactional File Locking is disabled." : "事务文件锁定已禁用。",
+ "SQLite is used as database. For larger installations we recommend to switch to a different database backend." : "SQLite 被用作数据库。对于较大数据量的安装和使用,我们建议您切换到不同的数据库后端。",
"Especially when using the desktop client for file syncing the use of SQLite is discouraged." : "特别当使用桌面客户端来同步文件时,不鼓励使用 SQLite 。",
+ "To migrate to another database use the command line tool: 'occ db:convert-type', or see the <a target=\"_blank\" href=\"%s\">documentation ↗</a>." : "要迁移到另一个数据库请使用命令行工具: 'occ db:convert-type', 或者查看 <a target=\\\"_blank\\\" href=\\\"%s\\\"> 相关文档 ↗</a>.",
+ "How to do backups" : "如何做备份",
"Advanced monitoring" : "高级监控",
"Performance tuning" : "性能优化",
"Improving the config.php" : "正在优化 config.php",
"Theming" : "主题",
+ "Hardening and security guidance" : "强化和安全指南",
"Version" : "版本",
+ "Developer documentation" : "开发者文档",
+ "Experimental applications ahead" : "未来的实验应用",
+ "Experimental apps are not checked for security issues, new or known to be unstable and under heavy development. Installing them can cause data loss or security breaches." : "实验应用程序没有在安全性的问题上作过多检查,新的或已知的不稳定 BUG 都在开发中。安装它们可能会导致数据丢失或安全漏洞。",
"by" : "被",
+ "licensed" : "许可",
"Documentation:" : "文档:",
"User documentation" : "用户文档",
+ "Admin documentation" : "管理员文档",
+ "Show description …" : "显示描述...",
+ "Hide description …" : "隐藏描述...",
+ "This app cannot be installed because the following dependencies are not fulfilled:" : "此应用程序无法安装,因为以下依赖性不满足:",
"Enable only for specific groups" : "仅对特定的组开放",
"Uninstall App" : "卸载应用",
+ "Enable experimental apps" : "启用实验性应用程序",
+ "No apps found for your version" : "未找到适合当前版本的应用",
+ "Hey there,<br><br>just letting you know that you now have an %s account.<br><br>Your username: %s<br>Access it: <a href=\"%s\">%s</a><br><br>" : "亲,<br><br>现在我们为你开通了 %s 私有云帐户。<br><br>你的用户名: %s<br>访问网址: <a href=\\\"%s\\\">%s</a><br><br>",
"Cheers!" : "干杯!",
+ "Hey there,\n\njust letting you know that you now have an %s account.\n\nYour username: %s\nAccess it: %s\n\n" : "亲,\\n\\n 现在我们为你开通了 %s 私有去帐户。\\n\\n 你的用户名: %s\\n 访问网址: %s\\n 你的初始密码需要咨询系统管理员。或者你也可以在登录页面输入任意密码登录,\\n登录窗口将出现忘记密码链接,点击通过注册邮箱重设初始密码。\\n\\n",
"Administrator documentation" : "管理员文档",
"Online documentation" : "在线文档",
"Forum" : "论坛",
+ "Issue tracker" : "问题跟踪",
+ "Commercial support" : "商业支持",
"Get the apps to sync your files" : "安装应用进行文件同步",
"Desktop client" : "桌面客户端",
"Android app" : "Android 应用",
@@ -154,13 +232,18 @@
"Current password" : "当前密码",
"New password" : "新密码",
"Change password" : "修改密码",
+ "Full name" : "全名",
+ "No display name set" : "不显示名称设置",
"Email" : "电子邮件",
"Your email address" : "您的电子邮件",
"Fill in an email address to enable password recovery and receive notifications" : "填入电子邮件地址从而启用密码恢复和接收通知",
+ "No email address set" : "尚未设置 Email 地址",
+ "You are member of the following groups:" : "您是以下组的成员:",
"Profile picture" : "联系人图片",
"Upload new" : "上传新的",
"Select new from Files" : "从文件中选择一个新的",
"Remove image" : "移除图片",
+ "Either png or jpg. Ideally square but you will be able to crop it. The file is not allowed to exceed the maximum size of 20 MB." : "png 或 jpg。正方形比较理想但你也可以之后对其进行裁剪。文件大小最大不允许超过 20MB。",
"Your avatar is provided by your original account." : "您的头像由您的原始账户所提供。",
"Cancel" : "取消",
"Choose as profile image" : "用作头像",
@@ -170,10 +253,15 @@
"Valid until" : "有效期至",
"Issued By" : "授权由",
"Valid until %s" : "有效期至 %s",
+ "Import root certificate" : "导入根证书",
"Developed by the {communityopen}ownCloud community{linkclose}, the {githubopen}source code{linkclose} is licensed under the {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr>{linkclose}." : "由 {communityopen}ownCloud 社区{linkclose}开发,{githubopen}源代码{linkclose}在 {licenseopen}<abbr title=\"Affero General Public License\">AGPL</abbr> 许可证{linkclose}下发布。",
"Show storage location" : "显示存储位置",
"Show last log in" : "显示最后登录",
+ "Show user backend" : "显示用户后端",
+ "Send email to new user" : "发送电子邮件给新用户",
+ "Show email address" : "显示邮件地址",
"Username" : "用户名",
+ "E-Mail" : "E-Mail",
"Create" : "创建",
"Admin Recovery Password" : "管理恢复密码",
"Enter the recovery password in order to recover the users files during password change" : "输入恢复密码来在更改密码的时候恢复用户文件",
@@ -186,6 +274,7 @@
"Unlimited" : "无限",
"Other" : "其它",
"Full Name" : "全名",
+ "Group Admin for" : "设为以下组管理员",
"Quota" : "配额",
"Storage Location" : "存储空间位置",
"User Backend" : "用户后端",
diff --git a/settings/languageCodes.php b/settings/languageCodes.php
index 729cc3c6af3..8c58079c2cb 100644
--- a/settings/languageCodes.php
+++ b/settings/languageCodes.php
@@ -26,6 +26,7 @@
return array(
'el'=>'Ελληνικά',
+'en'=>'English',
'fa'=>'فارسى',
'fi_FI'=>'Suomi',
'hi'=>'हिन्दी',
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index bd94ca67754..8bca05b1a18 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -8,6 +8,8 @@ if ($configDir) {
require_once __DIR__ . '/../lib/base.php';
+\OC::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
+
// load minimum set of apps
OC_App::loadApps(array('authentication'));
OC_App::loadApps(array('filesystem', 'logging'));
diff --git a/tests/core/command/encryption/changekeystorageroottest.php b/tests/core/command/encryption/changekeystorageroottest.php
new file mode 100644
index 00000000000..6cb52cdea99
--- /dev/null
+++ b/tests/core/command/encryption/changekeystorageroottest.php
@@ -0,0 +1,381 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace Tests\Core\Command\Encryption;
+
+
+use OC\Core\Command\Encryption\ChangeKeyStorageRoot;
+use OC\Encryption\Util;
+use OC\Files\View;
+use OCP\IConfig;
+use OCP\IUserManager;
+use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+class ChangeKeyStorageRootTest extends TestCase {
+
+ /** @var ChangeKeyStorageRoot */
+ protected $changeKeyStorageRoot;
+
+ /** @var View | \PHPUnit_Framework_MockObject_MockObject */
+ protected $view;
+
+ /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */
+ protected $userManager;
+
+ /** @var IConfig | \PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
+ /** @var Util | \PHPUnit_Framework_MockObject_MockObject */
+ protected $util;
+
+ /** @var QuestionHelper | \PHPUnit_Framework_MockObject_MockObject */
+ protected $questionHelper;
+
+ /** @var InputInterface | \PHPUnit_Framework_MockObject_MockObject */
+ protected $inputInterface;
+
+ /** @var OutputInterface | \PHPUnit_Framework_MockObject_MockObject */
+ protected $outputInterface;
+
+ /** @var \OCP\UserInterface | \PHPUnit_Framework_MockObject_MockObject */
+ protected $userInterface;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->view = $this->getMock('\OC\Files\View');
+ $this->userManager = $this->getMock('\OCP\IUserManager');
+ $this->config = $this->getMock('\OCP\IConfig');
+ $this->util = $this->getMockBuilder('OC\Encryption\Util')->disableOriginalConstructor()->getMock();
+ $this->questionHelper = $this->getMock('Symfony\Component\Console\Helper\QuestionHelper');
+ $this->inputInterface = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $this->outputInterface = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+ $this->userInterface = $this->getMock('\OCP\UserInterface');
+
+ $outputFormaterInterface = $this->getMock('Symfony\Component\Console\Formatter\OutputFormatterInterface');
+ $this->outputInterface->expects($this->any())->method('getFormatter')
+ ->willReturn($outputFormaterInterface);
+
+ $this->changeKeyStorageRoot = new ChangeKeyStorageRoot(
+ $this->view,
+ $this->userManager,
+ $this->config,
+ $this->util,
+ $this->questionHelper
+ );
+
+ }
+
+ /**
+ * @dataProvider dataTestExecute
+ */
+ public function testExecute($newRoot, $answer, $successMoveKey) {
+
+ $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot')
+ ->setConstructorArgs(
+ [
+ $this->view,
+ $this->userManager,
+ $this->config,
+ $this->util,
+ $this->questionHelper
+ ]
+ )->setMethods(['moveAllKeys'])->getMock();
+
+ $this->util->expects($this->once())->method('getKeyStorageRoot')
+ ->willReturn('');
+ $this->inputInterface->expects($this->once())->method('getArgument')
+ ->with('newRoot')->willReturn($newRoot);
+
+ if ($answer === true || $newRoot !== null) {
+ $changeKeyStorageRoot->expects($this->once())->method('moveAllKeys')
+ ->willReturn($successMoveKey);
+ } else {
+ $changeKeyStorageRoot->expects($this->never())->method('moveAllKeys');
+ }
+
+ if ($successMoveKey === true) {
+ $this->util->expects($this->once())->method('setKeyStorageRoot');
+ } else {
+ $this->util->expects($this->never())->method('setKeyStorageRoot');
+ }
+
+ if ($newRoot === null) {
+ $this->questionHelper->expects($this->once())->method('ask')->willReturn($answer);
+ } else {
+ $this->questionHelper->expects($this->never())->method('ask');
+ }
+
+ $this->invokePrivate(
+ $changeKeyStorageRoot,
+ 'execute',
+ [$this->inputInterface, $this->outputInterface]
+ );
+ }
+
+ public function dataTestExecute() {
+ return [
+ [null, true, true],
+ [null, true, false],
+ [null, false, null],
+ ['/newRoot', null, true],
+ ['/newRoot', null, false]
+ ];
+ }
+
+ public function testMoveAllKeys() {
+
+ /** @var \OC\Core\Command\Encryption\ChangeKeyStorageRoot $changeKeyStorageRoot */
+ $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot')
+ ->setConstructorArgs(
+ [
+ $this->view,
+ $this->userManager,
+ $this->config,
+ $this->util,
+ $this->questionHelper
+ ]
+ )->setMethods(['prepareNewRoot', 'moveSystemKeys', 'moveUserKeys'])->getMock();
+
+ $changeKeyStorageRoot->expects($this->at(0))->method('prepareNewRoot')->with('newRoot');
+ $changeKeyStorageRoot->expects($this->at(1))->method('moveSystemKeys')->with('oldRoot', 'newRoot');
+ $changeKeyStorageRoot->expects($this->at(2))->method('moveUserKeys')->with('oldRoot', 'newRoot', $this->outputInterface);
+
+ $this->invokePrivate($changeKeyStorageRoot, 'moveAllKeys', ['oldRoot', 'newRoot', $this->outputInterface]);
+
+ }
+
+ public function testPrepareNewRoot() {
+ $this->view->expects($this->once())->method('is_dir')->with('newRoot')
+ ->willReturn(true);
+
+ $this->view->expects($this->once())->method('file_put_contents')
+ ->with('newRoot/' . \OC\Encryption\Keys\Storage::KEY_STORAGE_MARKER,
+ 'ownCloud will detect this folder as key storage root only if this file exists');
+
+ $this->invokePrivate($this->changeKeyStorageRoot, 'prepareNewRoot', ['newRoot']);
+ }
+
+ /**
+ * @dataProvider dataTestPrepareNewRootException
+ * @expectedException \Exception
+ *
+ * @param bool $dirExists
+ * @param bool $couldCreateFile
+ */
+ public function testPrepareNewRootException($dirExists, $couldCreateFile) {
+ $this->view->expects($this->once())->method('is_dir')->with('newRoot')
+ ->willReturn($dirExists);
+ $this->view->expects($this->any())->method('file_put_contents')->willReturn($couldCreateFile);
+
+ $this->invokePrivate($this->changeKeyStorageRoot, 'prepareNewRoot', ['newRoot']);
+ }
+
+ public function dataTestPrepareNewRootException() {
+ return [
+ [true, false],
+ [false, true]
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestMoveSystemKeys
+ *
+ * @param bool $dirExists
+ * @param bool $targetExists
+ * @param bool $executeRename
+ */
+ public function testMoveSystemKeys($dirExists, $targetExists, $executeRename) {
+
+ $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot')
+ ->setConstructorArgs(
+ [
+ $this->view,
+ $this->userManager,
+ $this->config,
+ $this->util,
+ $this->questionHelper
+ ]
+ )->setMethods(['targetExists'])->getMock();
+
+ $this->view->expects($this->once())->method('is_dir')
+ ->with('oldRoot/files_encryption')->willReturn($dirExists);
+ $changeKeyStorageRoot->expects($this->any())->method('targetExists')
+ ->with('newRoot/files_encryption')->willReturn($targetExists);
+
+ if ($executeRename) {
+ $this->view->expects($this->once())->method('rename')
+ ->with('oldRoot/files_encryption', 'newRoot/files_encryption');
+ } else {
+ $this->view->expects($this->never())->method('rename');
+ }
+
+ $this->invokePrivate($changeKeyStorageRoot, 'moveSystemKeys', ['oldRoot', 'newRoot']);
+
+ }
+
+ public function dataTestMoveSystemKeys() {
+ return [
+ [true, false, true],
+ [false, true, false],
+ [true, true, false],
+ [false, false, false]
+ ];
+ }
+
+
+ public function testMoveUserKeys() {
+
+ $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot')
+ ->setConstructorArgs(
+ [
+ $this->view,
+ $this->userManager,
+ $this->config,
+ $this->util,
+ $this->questionHelper
+ ]
+ )->setMethods(['setupUserFS', 'moveUserEncryptionFolder'])->getMock();
+
+ $this->userManager->expects($this->once())->method('getBackends')
+ ->willReturn([$this->userInterface]);
+ $this->userInterface->expects($this->once())->method('getUsers')
+ ->willReturn(['user1', 'user2']);
+ $changeKeyStorageRoot->expects($this->exactly(2))->method('setupUserFS');
+ $changeKeyStorageRoot->expects($this->exactly(2))->method('moveUserEncryptionFolder');
+
+ $this->invokePrivate($changeKeyStorageRoot, 'moveUserKeys', ['oldRoot', 'newRoot', $this->outputInterface]);
+ }
+
+ /**
+ * @dataProvider dataTestMoveUserEncryptionFolder
+ *
+ * @param bool $userExists
+ * @param bool $isDir
+ * @param bool $targetExists
+ * @param bool $shouldRename
+ */
+ public function testMoveUserEncryptionFolder($userExists, $isDir, $targetExists, $shouldRename) {
+
+ $changeKeyStorageRoot = $this->getMockBuilder('OC\Core\Command\Encryption\ChangeKeyStorageRoot')
+ ->setConstructorArgs(
+ [
+ $this->view,
+ $this->userManager,
+ $this->config,
+ $this->util,
+ $this->questionHelper
+ ]
+ )->setMethods(['targetExists', 'prepareParentFolder'])->getMock();
+
+ $this->userManager->expects($this->once())->method('userExists')
+ ->willReturn($userExists);
+ $this->view->expects($this->any())->method('is_dir')
+ ->willReturn($isDir);
+ $changeKeyStorageRoot->expects($this->any())->method('targetExists')
+ ->willReturn($targetExists);
+
+ if ($shouldRename) {
+ $changeKeyStorageRoot->expects($this->once())->method('prepareParentFolder')
+ ->with('newRoot/user1');
+ $this->view->expects($this->once())->method('rename')
+ ->with('oldRoot/user1/files_encryption', 'newRoot/user1/files_encryption');
+ } else {
+ $changeKeyStorageRoot->expects($this->never())->method('prepareParentFolder');
+ $this->view->expects($this->never())->method('rename');
+ }
+
+ $this->invokePrivate($changeKeyStorageRoot, 'moveUserEncryptionFolder', ['user1', 'oldRoot', 'newRoot']);
+
+ }
+
+ public function dataTestMoveUserEncryptionFolder() {
+ return [
+ [true, true, false, true],
+ [true, false, true, false],
+ [false, true, true, false],
+ [false, false, true, false],
+ [false, true, false, false],
+ [false, true, true, false],
+ [false, false, false, false]
+ ];
+ }
+
+
+ /**
+ * @dataProvider dataTestPrepareParentFolder
+ */
+ public function testPrepareParentFolder($path, $pathExists) {
+ $this->view->expects($this->any())->method('file_exists')
+ ->willReturnCallback(
+ function($fileExistsPath) use ($path, $pathExists) {
+ if ($path === $fileExistsPath) {
+ return $pathExists;
+ }
+ return false;
+ }
+ );
+
+ if ($pathExists === false) {
+ $subDirs = explode('/', ltrim($path, '/'));
+ $this->view->expects($this->exactly(count($subDirs)))->method('mkdir');
+ } else {
+ $this->view->expects($this->never())->method('mkdir');
+ }
+
+ $this->invokePrivate(
+ $this->changeKeyStorageRoot,
+ 'prepareParentFolder',
+ [$path]
+ );
+ }
+
+ public function dataTestPrepareParentFolder() {
+ return [
+ ['/user/folder/sub_folder/keystorage', true],
+ ['/user/folder/sub_folder/keystorage', false]
+ ];
+ }
+
+ public function testTargetExists() {
+ $this->view->expects($this->once())->method('file_exists')->with('path')
+ ->willReturn(false);
+
+ $this->assertFalse(
+ $this->invokePrivate($this->changeKeyStorageRoot, 'targetExists', ['path'])
+ );
+ }
+
+ /**
+ * @expectedException \Exception
+ */
+ public function testTargetExistsException() {
+ $this->view->expects($this->once())->method('file_exists')->with('path')
+ ->willReturn(true);
+
+ $this->invokePrivate($this->changeKeyStorageRoot, 'targetExists', ['path']);
+ }
+
+}
diff --git a/tests/lib/appframework/http/HttpTest.php b/tests/lib/appframework/http/HttpTest.php
index e9be3e73904..4bcc8305db4 100644
--- a/tests/lib/appframework/http/HttpTest.php
+++ b/tests/lib/appframework/http/HttpTest.php
@@ -65,6 +65,14 @@ class HttpTest extends \Test\TestCase {
}
+ public function testQuotedEtagMatchReturnsNotModified() {
+ $http = new Http(array('HTTP_IF_NONE_MATCH' => '"hi"'));
+
+ $header = $http->getStatusHeader(Http::STATUS_OK, null, 'hi');
+ $this->assertEquals('HTTP/1.1 304 Not Modified', $header);
+ }
+
+
public function testLastModifiedMatchReturnsNotModified() {
$dateTime = new \DateTime(null, new \DateTimeZone('GMT'));
$dateTime->setTimestamp('12');
diff --git a/tests/lib/autoloader.php b/tests/lib/autoloader.php
index bf63094a9ef..6d9d3bd8eba 100644
--- a/tests/lib/autoloader.php
+++ b/tests/lib/autoloader.php
@@ -16,7 +16,7 @@ class AutoLoader extends TestCase {
protected function setUp() {
parent::setUp();
- $this->loader = new \OC\AutoLoader();
+ $this->loader = new \OC\AutoLoader([]);
}
public function testLeadingSlashOnClassName() {
diff --git a/tests/lib/encryption/keys/storage.php b/tests/lib/encryption/keys/storage.php
index 2f3aa3527b9..b5b91f886a3 100644
--- a/tests/lib/encryption/keys/storage.php
+++ b/tests/lib/encryption/keys/storage.php
@@ -37,6 +37,9 @@ class StorageTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $view;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+
public function setUp() {
parent::setUp();
@@ -48,6 +51,10 @@ class StorageTest extends TestCase {
->disableOriginalConstructor()
->getMock();
+ $this->config = $this->getMockBuilder('OCP\IConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+
$this->storage = new Storage($this->view, $this->util);
}
@@ -88,7 +95,7 @@ class StorageTest extends TestCase {
* @param bool $originalKeyExists
* @param string $expectedKeyContent
*/
- public function testGetFileKey2($path, $strippedPartialName, $originalKeyExists, $expectedKeyContent) {
+ public function testGetFileKey($path, $strippedPartialName, $originalKeyExists, $expectedKeyContent) {
$this->util->expects($this->any())
->method('getUidAndFilename')
->willReturnMap([
@@ -414,9 +421,12 @@ class StorageTest extends TestCase {
*
* @param string $path
* @param boolean $systemWideMountPoint
+ * @param string $storageRoot
* @param string $expected
*/
- public function testGetPathToKeys($path, $systemWideMountPoint, $expected) {
+ public function testGetPathToKeys($path, $systemWideMountPoint, $storageRoot, $expected) {
+
+ $this->invokePrivate($this->storage, 'root_dir', [$storageRoot]);
$this->util->expects($this->any())
->method('getUidAndFilename')
@@ -431,10 +441,12 @@ class StorageTest extends TestCase {
}
public function dataTestGetPathToKeys() {
- return array(
- array('/user1/files/source.txt', false, '/user1/files_encryption/keys/files/source.txt/'),
- array('/user1/files/source.txt', true, '/files_encryption/keys/files/source.txt/')
- );
+ return [
+ ['/user1/files/source.txt', false, '', '/user1/files_encryption/keys/files/source.txt/'],
+ ['/user1/files/source.txt', true, '', '/files_encryption/keys/files/source.txt/'],
+ ['/user1/files/source.txt', false, 'storageRoot', '/storageRoot/user1/files_encryption/keys/files/source.txt/'],
+ ['/user1/files/source.txt', true, 'storageRoot', '/storageRoot/files_encryption/keys/files/source.txt/'],
+ ];
}
public function testKeySetPreparation() {
@@ -463,4 +475,39 @@ class StorageTest extends TestCase {
$this->assertSame($expected, $args[0]);
}
+ /**
+ * @dataProvider dataTestGetFileKeyDir
+ *
+ * @param bool $isSystemWideMountPoint
+ * @param string $storageRoot
+ * @param string $expected
+ */
+ public function testGetFileKeyDir($isSystemWideMountPoint, $storageRoot, $expected) {
+
+ $path = '/user1/files/foo/bar.txt';
+ $owner = 'user1';
+ $relativePath = '/foo/bar.txt';
+
+ $this->invokePrivate($this->storage, 'root_dir', [$storageRoot]);
+
+ $this->util->expects($this->once())->method('isSystemWideMountPoint')
+ ->willReturn($isSystemWideMountPoint);
+ $this->util->expects($this->once())->method('getUidAndFilename')
+ ->with($path)->willReturn([$owner, $relativePath]);
+
+ $this->assertSame($expected,
+ $this->invokePrivate($this->storage, 'getFileKeyDir', ['OC_DEFAULT_MODULE', $path])
+ );
+
+ }
+
+ public function dataTestGetFileKeyDir() {
+ return [
+ [false, '', '/user1/files_encryption/keys/foo/bar.txt/OC_DEFAULT_MODULE/'],
+ [true, '', '/files_encryption/keys/foo/bar.txt/OC_DEFAULT_MODULE/'],
+ [false, 'newStorageRoot', '/newStorageRoot/user1/files_encryption/keys/foo/bar.txt/OC_DEFAULT_MODULE/'],
+ [true, 'newStorageRoot', '/newStorageRoot/files_encryption/keys/foo/bar.txt/OC_DEFAULT_MODULE/'],
+ ];
+ }
+
}
diff --git a/tests/lib/encryption/managertest.php b/tests/lib/encryption/managertest.php
index 9af7bc2c134..6355c706b61 100644
--- a/tests/lib/encryption/managertest.php
+++ b/tests/lib/encryption/managertest.php
@@ -19,12 +19,20 @@ class ManagerTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
private $l10n;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ private $view;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ private $util;
+
public function setUp() {
parent::setUp();
$this->config = $this->getMock('\OCP\IConfig');
$this->logger = $this->getMock('\OCP\ILogger');
$this->l10n = $this->getMock('\OCP\Il10n');
- $this->manager = new Manager($this->config, $this->logger, $this->l10n);
+ $this->view = $this->getMock('\OC\Files\View');
+ $this->util = $this->getMockBuilder('\OC\Encryption\Util')->disableOriginalConstructor()->getMock();
+ $this->manager = new Manager($this->config, $this->logger, $this->l10n, $this->view, $this->util);
}
public function testManagerIsDisabled() {
diff --git a/tests/lib/encryption/utiltest.php b/tests/lib/encryption/utiltest.php
index 5aadb4e857f..449326bb351 100644
--- a/tests/lib/encryption/utiltest.php
+++ b/tests/lib/encryption/utiltest.php
@@ -109,7 +109,11 @@ class UtilTest extends TestCase {
/**
* @dataProvider providePathsForTestIsExcluded
*/
- public function testIsExcluded($path, $expected) {
+ public function testIsExcluded($path, $keyStorageRoot, $expected) {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('core', 'encryption_key_storage_root', '')
+ ->willReturn($keyStorageRoot);
$this->userManager
->expects($this->any())
->method('userExists')
@@ -122,11 +126,14 @@ class UtilTest extends TestCase {
public function providePathsForTestIsExcluded() {
return array(
- array('/files_encryption', true),
- array('files_encryption/foo.txt', true),
- array('test/foo.txt', false),
- array('/user1/files_encryption/foo.txt', true),
- array('/user1/files/foo.txt', false),
+ array('/files_encryption', '', true),
+ array('files_encryption/foo.txt', '', true),
+ array('test/foo.txt', '', false),
+ array('/user1/files_encryption/foo.txt', '', true),
+ array('/user1/files/foo.txt', '', false),
+ array('/keyStorage/user1/files/foo.txt', 'keyStorage', true),
+ array('/keyStorage/files_encryption', '/keyStorage', true),
+ array('keyStorage/user1/files_encryption', '/keyStorage/', true),
);
}
diff --git a/tests/lib/security/certificatemanager.php b/tests/lib/security/certificatemanager.php
index fab1c208443..092f9efdd18 100644
--- a/tests/lib/security/certificatemanager.php
+++ b/tests/lib/security/certificatemanager.php
@@ -26,7 +26,11 @@ class CertificateManagerTest extends \Test\TestCase {
\OC\Files\Filesystem::tearDown();
\OC_Util::setupFS($this->username);
- $this->certificateManager = new CertificateManager($this->username, new \OC\Files\View());
+ $config = $this->getMock('OCP\IConfig');
+ $config->expects($this->any())->method('getSystemValue')
+ ->with('installed', false)->willReturn(true);
+
+ $this->certificateManager = new CertificateManager($this->username, new \OC\Files\View(), $config);
}
protected function tearDown() {
diff --git a/tests/lib/template.php b/tests/lib/template.php
index db58238eae8..6e62d3955f1 100644
--- a/tests/lib/template.php
+++ b/tests/lib/template.php
@@ -1,31 +1,31 @@
<?php
-/**
-* ownCloud
-*
-* @author Bernhard Posselt
-* @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com>
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 of the License, or any later version.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
+/**
+ * ownCloud
+ *
+ * @author Bernhard Posselt
+ * @copyright 2012 Bernhard Posselt <dev@bernhard-posselt.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
class Test_TemplateFunctions extends \Test\TestCase {
protected function setUp() {
parent::setUp();
- $loader = new \OC\Autoloader();
+ $loader = new \OC\Autoloader([OC::$SERVERROOT . '/lib']);
$loader->load('OC_Template');
}
@@ -60,7 +60,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
// ---------------------------------------------------------------------------
// Test relative_modified_date with dates only
// ---------------------------------------------------------------------------
- public function testRelativeDateToday(){
+ public function testRelativeDateToday() {
$currentTime = 1380703592;
$elementTime = $currentTime;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -74,7 +74,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('today', $result);
}
- public function testRelativeDateYesterday(){
+ public function testRelativeDateYesterday() {
$currentTime = 1380703592;
$elementTime = $currentTime - 24 * 3600;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -88,7 +88,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('yesterday', $result);
}
- public function testRelativeDate2DaysAgo(){
+ public function testRelativeDate2DaysAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 48 * 3600;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -102,7 +102,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('2 days ago', $result);
}
- public function testRelativeDateLastMonth(){
+ public function testRelativeDateLastMonth() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 31;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -115,7 +115,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('last month', $result);
}
- public function testRelativeDateMonthsAgo(){
+ public function testRelativeDateMonthsAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 65;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -128,7 +128,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('4 months ago', $result);
}
- public function testRelativeDateLastYear(){
+ public function testRelativeDateLastYear() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 365;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -141,7 +141,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('last year', $result);
}
- public function testRelativeDateYearsAgo(){
+ public function testRelativeDateYearsAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 365.25 * 2;
$result = (string)relative_modified_date($elementTime, $currentTime, true);
@@ -158,7 +158,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
// Test relative_modified_date with timestamps only (date + time value)
// ---------------------------------------------------------------------------
- public function testRelativeTimeSecondsAgo(){
+ public function testRelativeTimeSecondsAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 5;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -166,7 +166,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('seconds ago', $result);
}
- public function testRelativeTimeMinutesAgo(){
+ public function testRelativeTimeMinutesAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 190;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -174,7 +174,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('3 minutes ago', $result);
}
- public function testRelativeTimeHoursAgo(){
+ public function testRelativeTimeHoursAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 7500;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -182,7 +182,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('2 hours ago', $result);
}
- public function testRelativeTime2DaysAgo(){
+ public function testRelativeTime2DaysAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 48 * 3600;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -196,7 +196,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('2 days ago', $result);
}
- public function testRelativeTimeLastMonth(){
+ public function testRelativeTimeLastMonth() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 31;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -209,7 +209,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('last month', $result);
}
- public function testRelativeTimeMonthsAgo(){
+ public function testRelativeTimeMonthsAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 65;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -222,7 +222,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('4 months ago', $result);
}
- public function testRelativeTimeLastYear(){
+ public function testRelativeTimeLastYear() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 365;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
@@ -235,7 +235,7 @@ class Test_TemplateFunctions extends \Test\TestCase {
$this->assertEquals('last year', $result);
}
- public function testRelativeTimeYearsAgo(){
+ public function testRelativeTimeYearsAgo() {
$currentTime = 1380703592;
$elementTime = $currentTime - 86400 * 365.25 * 2;
$result = (string)relative_modified_date($elementTime, $currentTime, false);
diff --git a/tests/settings/controller/CheckSetupControllerTest.php b/tests/settings/controller/CheckSetupControllerTest.php
index 414b1b91e17..2a8a6548ebb 100644
--- a/tests/settings/controller/CheckSetupControllerTest.php
+++ b/tests/settings/controller/CheckSetupControllerTest.php
@@ -384,6 +384,11 @@ class CheckSetupControllerTest extends TestCase {
}
public function testIsUsedTlsLibOutdatedWithOlderOpenSsl() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(true));
$this->checkSetupController
->expects($this->once())
->method('getCurlVersion')
@@ -391,7 +396,25 @@ class CheckSetupControllerTest extends TestCase {
$this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.1c). Please update your operating system or features such as installing and updating apps via the app store or Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
}
+ public function testIsUsedTlsLibOutdatedWithOlderOpenSslAndWithoutAppstore() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(false));
+ $this->checkSetupController
+ ->expects($this->once())
+ ->method('getCurlVersion')
+ ->will($this->returnValue(['ssl_version' => 'OpenSSL/1.0.1c']));
+ $this->assertSame('cURL is using an outdated OpenSSL version (OpenSSL/1.0.1c). Please update your operating system or features such as Federated Cloud Sharing will not work reliably.', $this->invokePrivate($this->checkSetupController, 'isUsedTlsLibOutdated'));
+ }
+
public function testIsUsedTlsLibOutdatedWithOlderOpenSsl1() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(true));
$this->checkSetupController
->expects($this->once())
->method('getCurlVersion')
@@ -416,6 +439,11 @@ class CheckSetupControllerTest extends TestCase {
}
public function testIsBuggyNss400() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstoreenabled', true)
+ ->will($this->returnValue(true));
$this->checkSetupController
->expects($this->once())
->method('getCurlVersion')