diff --git a/.gitignore b/.gitignore index e61ec6f035930b0cf4da454aab61374f46b82c1c..b24edc912828e8f0f8653c3207bca152f6c0737e 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,11 @@ nbproject # Node Modules /build/node_modules/ +# nodejs +/build/lib/ +/npm-debug.log + + # Tests - auto-generated files /data-autotest /tests/coverage* diff --git a/.gitmodules b/.gitmodules index b9c1a3702cfb2f5dbc88f54aca9a46a246c97550..bc2beee81adcc479e0b251f09063dcffb08f8d81 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "3rdparty"] path = 3rdparty - url = git://github.com/owncloud/3rdparty.git + url = https://github.com/owncloud/3rdparty.git diff --git a/.jshintrc b/.jshintrc index 90cec5c5961fe670860b05af2027325fd64ddd30..77f9e9f143d4c155ea03549df18202cef36decd4 100644 --- a/.jshintrc +++ b/.jshintrc @@ -11,18 +11,22 @@ "maxparams": 5, "curly": true, "jquery": true, - "maxlen": 80, + "maxlen": 120, "indent": 4, "browser": true, "globals": { "console": true, "it": true, - "itx": true, + "xit": true, "expect": true, "describe": true, "beforeEach": true, "afterEach": true, "sinon": true, - "fakeServer": true + "fakeServer": true, + "_": true, + "OC": true, + "t": true, + "n": true } } diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 4473cf9056d5ccd6094622604b86337dd70b94bb..fa05b9b8a407f78d604ea685c6d65b5314a9ca95 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -7,6 +7,7 @@ filter: - 'apps/*/l10n/*' - 'lib/l10n/*' - 'core/js/tests/lib/*.js' + - 'core/js/tests/specs/*.js' - 'core/js/jquery-1.10.0.min.js' - 'core/js/jquery-migrate-1.2.1.min.js' - 'core/js/jquery-showpassword.js' @@ -15,6 +16,8 @@ filter: - 'core/js/jquery-ui-1.10.0.custom.js' - 'core/js/jquery.inview.js' - 'core/js/jquery.placeholder.js' + - 'core/js/underscore.js' + - 'core/js/jquery.multiselect.js' imports: diff --git a/README.md b/README.md index 3f76c1a4773bc3a2f37794f9422ae0476b01802e..0b13f11e76803e46019218525941e769a8f8d9fe 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,14 @@ Git master: [![Build Status](https://ci.owncloud.org/job/server-master-linux/bad Quality: [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/owncloud/core/badges/quality-score.png?s=ce2f5ded03d4ac628e9ee5c767243fa7412e644f)](https://scrutinizer-ci.com/g/owncloud/core/) ### Installation instructions -http://doc.owncloud.org/server/5.0/developer_manual/app/gettingstarted.html +http://doc.owncloud.org/server/7.0/developer_manual/app/index.html ### Contribution Guidelines -http://owncloud.org/dev/contribute/ +http://owncloud.org/contribute/ ### Get in touch * [Forum](http://forum.owncloud.org) -* [Mailing list](https://mail.kde.org/mailman/listinfo/owncloud) +* [Mailing list](http://mailman.owncloud.org/mailman/listinfo) * [IRC channel](https://webchat.freenode.net/?channels=owncloud) * [Twitter](https://twitter.com/ownClouders) @@ -25,4 +25,4 @@ Please submit translations via Transifex: https://www.transifex.com/projects/p/owncloud/ For more detailed information about translations: -http://owncloud.org/dev/translation/ +http://doc.owncloud.org/server/7.0/developer_manual/core/translation.html diff --git a/apps/files/ajax/download.php b/apps/files/ajax/download.php index 1f7e42e0d3e3b282487bd2e811e032ef93b95788..4b4a7f8948d4d2bbd1a2a19fec65484b79fa1285 100644 --- a/apps/files/ajax/download.php +++ b/apps/files/ajax/download.php @@ -21,12 +21,6 @@ * */ -// only need filesystem apps -$RUNTIME_APPTYPES=array('filesystem'); - -// Init owncloud - - // Check if we are a user OCP\User::checkLoggedIn(); \OC::$session->close(); diff --git a/apps/files/ajax/getstoragestats.php b/apps/files/ajax/getstoragestats.php index 17415b6933f09d4b1ef35241bada4d35db3ec946..dd8af39bada3ec55abb2c0fde56b000463823faa 100644 --- a/apps/files/ajax/getstoragestats.php +++ b/apps/files/ajax/getstoragestats.php @@ -1,8 +1,5 @@ close(); @@ -13,37 +7,21 @@ OCP\JSON::checkLoggedIn(); $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; $dir = \OC\Files\Filesystem::normalizePath($dir); $dirInfo = \OC\Files\Filesystem::getFileInfo($dir); -if (!$dirInfo->getType() === 'dir') { +if (!$dirInfo || !$dirInfo->getType() === 'dir') { header("HTTP/1.0 404 Not Found"); exit(); } -$doBreadcrumb = isset($_GET['breadcrumb']); $data = array(); $baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir='; $permissions = $dirInfo->getPermissions(); -// Make breadcrumb -if($doBreadcrumb) { - $breadcrumb = \OCA\Files\Helper::makeBreadcrumb($dir); - - $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); - $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); - $breadcrumbNav->assign('baseURL', $baseUrl); - - $data['breadcrumb'] = $breadcrumbNav->fetchPage(); -} - // make filelist $files = \OCA\Files\Helper::getFiles($dir); -$list = new OCP\Template("files", "part.list", ""); -$list->assign('files', $files, false); -$list->assign('baseURL', $baseUrl, false); -$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); -$list->assign('isPublic', false); -$data['files'] = $list->fetchPage(); +$data['directory'] = $dir; +$data['files'] = \OCA\Files\Helper::formatFileInfos($files); $data['permissions'] = $permissions; OCP\JSON::success(array('data' => $data)); diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 1234cf11394342dfb655c97687197a8b7f32f06a..7d6be59beab2b9e29c257fa9a5192b71db7a3000 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -112,9 +112,8 @@ if($source) { } if($result) { $meta = \OC\Files\Filesystem::getFileInfo($target); - $mime=$meta['mimetype']; - $id = $meta['fileid']; - $eventSource->send('success', array('mime' => $mime, 'size' => \OC\Files\Filesystem::filesize($target), 'id' => $id, 'etag' => $meta['etag'])); + $data = \OCA\Files\Helper::formatFileInfo($meta); + $eventSource->send('success', $data); } else { $eventSource->send('error', array('message' => $l10n->t('Error while downloading %s to %s', array($source, $target)))); } @@ -139,16 +138,7 @@ if($source) { if($success) { $meta = \OC\Files\Filesystem::getFileInfo($target); - $id = $meta['fileid']; - $mime = $meta['mimetype']; - $size = $meta['size']; - OCP\JSON::success(array('data' => array( - 'id' => $id, - 'mime' => $mime, - 'size' => $size, - 'content' => $content, - 'etag' => $meta['etag'], - ))); + OCP\JSON::success(array('data' => \OCA\Files\Helper::formatFileInfo($meta))); exit(); } } diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index 032447460f3fb0961c4c0251e6f02aa7b5b6a34c..89c241189d71cf8f0fc3332e4c79925e58a79d4b 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -58,8 +58,8 @@ if(\OC\Files\Filesystem::mkdir($target)) { $path = '/'.$foldername; } $meta = \OC\Files\Filesystem::getFileInfo($path); - $id = $meta['fileid']; - OCP\JSON::success(array('data' => array('id' => $id))); + $meta['type'] = 'dir'; // missing ?! + OCP\JSON::success(array('data' => \OCA\Files\Helper::formatFileInfo($meta))); exit(); } diff --git a/apps/files/ajax/rawlist.php b/apps/files/ajax/rawlist.php deleted file mode 100644 index 6c2569e2ebbc903d86d196ce55561724e3ea407a..0000000000000000000000000000000000000000 --- a/apps/files/ajax/rawlist.php +++ /dev/null @@ -1,57 +0,0 @@ -close(); - -// Load the files -$dir = isset($_GET['dir']) ? $_GET['dir'] : ''; -$mimetypes = isset($_GET['mimetypes']) ? json_decode($_GET['mimetypes'], true) : ''; - -// Clean up duplicates from array and deal with non-array requests -if (is_array($mimetypes)) { - $mimetypes = array_unique($mimetypes); -} elseif (is_null($mimetypes)) { - $mimetypes = array($_GET['mimetypes']); -} - -// make filelist -$files = array(); -/** - * @var \OCP\Files\FileInfo[] $files - */ -// If a type other than directory is requested first load them. -if ($mimetypes && !in_array('httpd/unix-directory', $mimetypes)) { - $files = array_merge($files, \OC\Files\Filesystem::getDirectoryContent($dir, 'httpd/unix-directory')); -} - -if (is_array($mimetypes) && count($mimetypes)) { - foreach ($mimetypes as $mimetype) { - $files = array_merge($files, \OC\Files\Filesystem::getDirectoryContent($dir, $mimetype)); - } -} else { - $files = array_merge($files, \OC\Files\Filesystem::getDirectoryContent($dir)); -} -// Sort by name -usort($files, array('\OCA\Files\Helper', 'fileCmp')); - -$result = array(); -foreach ($files as $file) { - $fileData = array(); - $fileData['directory'] = $dir; - $fileData['name'] = $file->getName(); - $fileData['type'] = $file->getType(); - $fileData['path'] = $file['path']; - $fileData['id'] = $file->getId(); - $fileData['size'] = $file->getSize(); - $fileData['mtime'] = $file->getMtime(); - $fileData['mimetype'] = $file->getMimetype(); - $fileData['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($file->getMimetype()); - $fileData["date"] = OCP\Util::formatDate($file->getMtime()); - $fileData['mimetype_icon'] = \OCA\Files\Helper::determineIcon($file); - $result[] = $fileData; -} - -OC_JSON::success(array('data' => $result)); diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 4ed51c527759b49d4626016e44f36e69a3e72083..b21a9dfba2ed256e077233d94272201c9516c2ff 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -20,6 +20,10 @@ if (empty($_POST['dirToken'])) { die(); } } else { + // TODO: ideally this code should be in files_sharing/ajax/upload.php + // and the upload/file transfer code needs to be refactored into a utility method + // that could be used there + // return only read permissions for public upload $allowedPermissions = OCP\PERMISSION_READ; $public_directory = !empty($_POST['subdir']) ? $_POST['subdir'] : '/'; @@ -141,19 +145,14 @@ if (strpos($dir, '..') === false) { $error = $l->t('The target folder has been moved or deleted.'); $errorCode = 'targetnotfound'; } else { - $result[] = array('status' => 'success', - 'mime' => $meta['mimetype'], - 'mtime' => $meta['mtime'], - 'size' => $meta['size'], - 'id' => $meta['fileid'], - 'name' => basename($target), - 'etag' => $meta['etag'], - 'originalname' => $files['tmp_name'][$i], - 'uploadMaxFilesize' => $maxUploadFileSize, - 'maxHumanFilesize' => $maxHumanFileSize, - 'permissions' => $meta['permissions'] & $allowedPermissions, - 'directory' => $directory, - ); + $data = \OCA\Files\Helper::formatFileInfo($meta); + $data['status'] = 'success'; + $data['originalname'] = $files['tmp_name'][$i]; + $data['uploadMaxFilesize'] = $maxUploadFileSize; + $data['maxHumanFilesize'] = $maxHumanFileSize; + $data['permissions'] = $meta['permissions'] & $allowedPermissions; + $data['directory'] = $directory; + $result[] = $data; } } else { @@ -169,19 +168,15 @@ if (strpos($dir, '..') === false) { if ($meta === false) { $error = $l->t('Upload failed. Could not get file info.'); } else { - $result[] = array('status' => 'existserror', - 'mime' => $meta['mimetype'], - 'mtime' => $meta['mtime'], - 'size' => $meta['size'], - 'id' => $meta['fileid'], - 'name' => basename($target), - 'etag' => $meta['etag'], - 'originalname' => $files['tmp_name'][$i], - 'uploadMaxFilesize' => $maxUploadFileSize, - 'maxHumanFilesize' => $maxHumanFileSize, - 'permissions' => $meta['permissions'] & $allowedPermissions, - 'directory' => $directory, - ); + $data = \OCA\Files\Helper::formatFileInfo($meta); + $data['permissions'] = $data['permissions'] & $allowedPermissions; + $data['status'] = 'existserror'; + $data['originalname'] = $files['tmp_name'][$i]; + $data['uploadMaxFilesize'] = $maxUploadFileSize; + $data['maxHumanFilesize'] = $maxHumanFileSize; + $data['permissions'] = $meta['permissions'] & $allowedPermissions; + $data['directory'] = $directory; + $result[] = $data; } } } diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php index 1b2d144da5c81f305012d3e153516b86a98dd4fa..c1baee4f1ef985d99aa84caa45f15cb9a19d9708 100644 --- a/apps/files/appinfo/remote.php +++ b/apps/files/appinfo/remote.php @@ -22,12 +22,6 @@ * License along with this library. If not, see . * */ -// load needed apps -$RUNTIME_APPTYPES = array('filesystem', 'authentication', 'logging'); - -OC_App::loadApps($RUNTIME_APPTYPES); - -OC_Util::obEnd(); // Backends $authBackend = new OC_Connector_Sabre_Auth(); @@ -44,6 +38,7 @@ $server->setBaseUri($baseuri); $defaults = new OC_Defaults(); $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, $defaults->getName())); $server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend)); +$server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); $server->addPlugin(new OC_Connector_Sabre_FilesPlugin()); $server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin()); $server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav')); diff --git a/apps/files/command/scan.php b/apps/files/command/scan.php index f334f29a939e3002600212d079b22b45c6087c5f..25ab70af3629a7d50940c589f1b6cd41c52dd62b 100644 --- a/apps/files/command/scan.php +++ b/apps/files/command/scan.php @@ -58,7 +58,6 @@ class Scan extends Command { protected function execute(InputInterface $input, OutputInterface $output) { if ($input->getOption('all')) { - \OC_App::loadApps('authentication'); $users = $this->userManager->search(''); } else { $users = $input->getArgument('user_id'); diff --git a/apps/files/css/files.css b/apps/files/css/files.css index af863aca33ebe14aac52dbfaa0ddb100c2334222..1bac5d2b7db26bdb2857d5d7c794debed1a67489 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -77,10 +77,10 @@ } /* make sure there's enough room for the file actions */ #body-user #filestable { - min-width: 750px; + min-width: 688px; /* 768 (mobile break) - 80 (nav width) */ } #body-user #controls { - min-width: 600px; + min-width: 688px; /* 768 (mobile break) - 80 (nav width) */ } #filestable tbody tr { background-color:#fff; height:40px; } diff --git a/apps/files/css/mobile.css b/apps/files/css/mobile.css new file mode 100644 index 0000000000000000000000000000000000000000..3ad7d63483869f99358a24f0c84afd611bb54354 --- /dev/null +++ b/apps/files/css/mobile.css @@ -0,0 +1,68 @@ +@media only screen and (max-width: 768px) { + +/* don’t require a minimum width for files table */ +#body-user #filestable { + min-width: initial !important; +} + +/* do not show Deleted Files on mobile, not optimized yet and button too long */ +#controls #trash { + display: none; +} + +/* hide size and date columns */ +table th#headerSize, +table td.filesize, +table th#headerDate, +table td.date { + display: none; +} + +/* remove shift for multiselect bar to account for missing navigation */ +table.multiselect thead { + padding-left: 0; +} + +/* restrict length of displayed filename to prevent overflow */ +table td.filename .nametext { + max-width: 75% !important; +} + +/* always show actions on mobile, not only on hover */ +#fileList a.action { + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)" !important; + filter: alpha(opacity=20) !important; + opacity: .2 !important; + display: inline !important; +} +/* do not show Rename or Versions on mobile */ +#fileList .action.action-rename, +#fileList .action.action-versions { + display: none !important; +} +/* some padding for better clickability */ +#fileList a.action img { + padding: 0 6px 0 12px; +} +/* hide text of the actions on mobile */ +#fileList a.action span { + display: none; +} + +/* ellipsis on file names */ +.nametext { + width: 60%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* proper notification area for multi line messages */ +#notification-container { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; +} +} diff --git a/apps/files/index.php b/apps/files/index.php index c66cd40fb56150a981079c7536f413cb40617ceb..b8ff08c1b05573dadcd74aaeac5dc4d71581f625 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -27,19 +27,21 @@ OCP\User::checkLoggedIn(); // Load the files we need OCP\Util::addStyle('files', 'files'); OCP\Util::addStyle('files', 'upload'); +OCP\Util::addStyle('files', 'mobile'); OCP\Util::addscript('files', 'file-upload'); OCP\Util::addscript('files', 'jquery.iframe-transport'); OCP\Util::addscript('files', 'jquery.fileupload'); OCP\Util::addscript('files', 'jquery-visibility'); +OCP\Util::addscript('files', 'breadcrumb'); OCP\Util::addscript('files', 'filelist'); OCP\App::setActiveNavigationEntry('files_index'); // Load the files $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; $dir = \OC\Files\Filesystem::normalizePath($dir); -$dirInfo = \OC\Files\Filesystem::getFileInfo($dir); +$dirInfo = \OC\Files\Filesystem::getFileInfo($dir, false); // Redirect if directory does not exist -if (!$dirInfo->getType() === 'dir') { +if (!$dirInfo || !$dirInfo->getType() === 'dir') { header('Location: ' . OCP\Util::getScriptName() . ''); exit(); } @@ -59,44 +61,19 @@ if ($isIE8 && isset($_GET['dir'])){ exit(); } -$ajaxLoad = false; -$files = array(); $user = OC_User::getUser(); -if ($isIE8){ - // after the redirect above, the URL will have a format - // like "files#?dir=path" which means that no path was given - // (dir is not set). In that specific case, we don't return any - // files because the client will take care of switching the dir - // to the one from the hash, then ajax-load the initial file list - $files = array(); - $ajaxLoad = true; -} -else{ - $files = \OCA\Files\Helper::getFiles($dir); -} $config = \OC::$server->getConfig(); -// Make breadcrumb -$breadcrumb = \OCA\Files\Helper::makeBreadcrumb($dir); - -// make breadcrumb und filelist markup -$list = new OCP\Template('files', 'part.list', ''); -$list->assign('files', $files); -$list->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); -$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); -$list->assign('isPublic', false); -$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); -$breadcrumbNav->assign('breadcrumb', $breadcrumb); -$breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files', 'index.php') . '?dir='); - +// needed for share init, permissions will be reloaded +// anyway with ajax load $permissions = $dirInfo->getPermissions(); // information about storage capacities -$storageInfo=OC_Helper::getStorageInfo($dir); +$storageInfo=OC_Helper::getStorageInfo($dir, $dirInfo); $freeSpace=$storageInfo['free']; $uploadLimit=OCP\Util::uploadLimit(); -$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); +$maxUploadFilesize=OCP\Util::maxUploadFilesize($dir, $freeSpace); $publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); // if the encryption app is disabled, than everything is fine (INIT_SUCCESSFUL status code) $encryptionInitStatus = 2; @@ -111,20 +88,12 @@ if ($trashEnabled) { $trashEmpty = \OCA\Files_Trashbin\Trashbin::isEmpty($user); } -$isCreatable = \OC\Files\Filesystem::isCreatable($dir . '/'); -$fileHeader = (!isset($files) or count($files) > 0); -$emptyContent = ($isCreatable and !$fileHeader) or $ajaxLoad; - OCP\Util::addscript('files', 'fileactions'); OCP\Util::addscript('files', 'files'); OCP\Util::addscript('files', 'keyboardshortcuts'); $tmpl = new OCP\Template('files', 'index', 'user'); -$tmpl->assign('fileList', $list->fetchPage()); -$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage()); $tmpl->assign('dir', $dir); -$tmpl->assign('isCreatable', $isCreatable); $tmpl->assign('permissions', $permissions); -$tmpl->assign('files', $files); $tmpl->assign('trash', $trashEnabled); $tmpl->assign('trashEmpty', $trashEmpty); $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); // minimium of freeSpace and uploadLimit @@ -140,8 +109,5 @@ $tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_ $tmpl->assign("allowShareWithLink", $config->getAppValue('core', 'shareapi_allow_links', 'yes')); $tmpl->assign("encryptionInitStatus", $encryptionInitStatus); $tmpl->assign('disableSharing', false); -$tmpl->assign('ajaxLoad', $ajaxLoad); -$tmpl->assign('emptyContent', $emptyContent); -$tmpl->assign('fileHeader', $fileHeader); $tmpl->printPage(); diff --git a/apps/files/js/breadcrumb.js b/apps/files/js/breadcrumb.js new file mode 100644 index 0000000000000000000000000000000000000000..5bc2fac13695d29940872c4dfa6e76931035e923 --- /dev/null +++ b/apps/files/js/breadcrumb.js @@ -0,0 +1,241 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2014 Vincent Petry +* +* 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 . +* +*/ + +/* global OC */ +(function() { + /** + * Creates an breadcrumb element in the given container + */ + var BreadCrumb = function(options){ + this.$el = $(''); + options = options || {}; + if (options.onClick) { + this.onClick = options.onClick; + } + if (options.onDrop) { + this.onDrop = options.onDrop; + } + if (options.getCrumbUrl) { + this.getCrumbUrl = options.getCrumbUrl; + } + }; + BreadCrumb.prototype = { + $el: null, + dir: null, + + lastWidth: 0, + hiddenBreadcrumbs: 0, + totalWidth: 0, + breadcrumbs: [], + onClick: null, + onDrop: null, + + /** + * Sets the directory to be displayed as breadcrumb. + * This will re-render the breadcrumb. + * @param dir path to be displayed as breadcrumb + */ + setDirectory: function(dir) { + dir = dir || '/'; + if (dir !== this.dir) { + this.dir = dir; + this.render(); + } + }, + + /** + * Returns the full URL to the given directory + * @param part crumb data as map + * @param index crumb index + * @return full URL + */ + getCrumbUrl: function(part, index) { + return '#'; + }, + + /** + * Renders the breadcrumb elements + */ + render: function() { + var parts = this._makeCrumbs(this.dir || '/'); + var $crumb; + this.$el.empty(); + this.breadcrumbs = []; + + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + var $image; + var $link = $('').attr('href', this.getCrumbUrl(part, i)); + $link.text(part.name); + $crumb = $('
'); + $crumb.append($link); + $crumb.attr('data-dir', part.dir); + + if (part.img) { + $image = $(''); + $image.attr('src', part.img); + $link.append($image); + } + this.breadcrumbs.push($crumb); + this.$el.append($crumb); + if (this.onClick) { + $crumb.on('click', this.onClick); + } + } + $crumb.addClass('last'); + + // in case svg is not supported by the browser we need to execute the fallback mechanism + if (!OC.Util.hasSVGSupport()) { + OC.Util.replaceSVG(this.$el); + } + + // setup drag and drop + if (this.onDrop) { + this.$el.find('.crumb:not(.last)').droppable({ + drop: this.onDrop, + tolerance: 'pointer' + }); + } + + this._updateTotalWidth(); + this.resize($(window).width(), true); + }, + + /** + * Makes a breadcrumb structure based on the given path + * @param dir path to split into a breadcrumb structure + * @return array of map {dir: path, name: displayName} + */ + _makeCrumbs: function(dir) { + var crumbs = []; + var pathToHere = ''; + // trim leading and trailing slashes + dir = dir.replace(/^\/+|\/+$/g, ''); + var parts = dir.split('/'); + if (dir === '') { + parts = []; + } + // root part + crumbs.push({ + dir: '/', + name: '', + img: OC.imagePath('core', 'places/home.svg') + }); + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + pathToHere = pathToHere + '/' + part; + crumbs.push({ + dir: pathToHere, + name: part + }); + } + return crumbs; + }, + + _updateTotalWidth: function () { + var self = this; + + this.lastWidth = 0; + + // initialize with some extra space + this.totalWidth = 64; + // FIXME: this class should not know about global elements + if ( $('#navigation').length ) { + this.totalWidth += $('#navigation').get(0).offsetWidth; + } + this.hiddenBreadcrumbs = 0; + + for (var i = 0; i < this.breadcrumbs.length; i++ ) { + this.totalWidth += $(this.breadcrumbs[i]).get(0).offsetWidth; + } + + $.each($('#controls .actions>div'), function(index, action) { + self.totalWidth += $(action).get(0).offsetWidth; + }); + + }, + + /** + * Show/hide breadcrumbs to fit the given width + */ + resize: function (width, firstRun) { + var i, $crumb; + + if (width === this.lastWidth) { + return; + } + + // window was shrinked since last time or first run ? + if ((width < this.lastWidth || firstRun) && width < this.totalWidth) { + if (this.hiddenBreadcrumbs === 0 && this.breadcrumbs.length > 1) { + // start by hiding the first breadcrumb after home, + // that one will have extra three dots displayed + $crumb = this.breadcrumbs[1]; + this.totalWidth -= $crumb.get(0).offsetWidth; + $crumb.find('a').addClass('hidden'); + $crumb.append('...'); + this.totalWidth += $crumb.get(0).offsetWidth; + this.hiddenBreadcrumbs = 2; + } + i = this.hiddenBreadcrumbs; + // hide subsequent breadcrumbs if the space is still not enough + while (width < this.totalWidth && i > 1 && i < this.breadcrumbs.length - 1) { + $crumb = this.breadcrumbs[i]; + this.totalWidth -= $crumb.get(0).offsetWidth; + $crumb.addClass('hidden'); + this.hiddenBreadcrumbs = i; + i++; + } + // window is bigger than last time + } else if (width > this.lastWidth && this.hiddenBreadcrumbs > 0) { + i = this.hiddenBreadcrumbs; + while (width > this.totalWidth && i > 0) { + if (this.hiddenBreadcrumbs === 1) { + // special handling for last one as it has the three dots + $crumb = this.breadcrumbs[1]; + if ($crumb) { + this.totalWidth -= $crumb.get(0).offsetWidth; + $crumb.find('.ellipsis').remove(); + $crumb.find('a').removeClass('hidden'); + this.totalWidth += $crumb.get(0).offsetWidth; + } + } else { + $crumb = this.breadcrumbs[i]; + $crumb.removeClass('hidden'); + this.totalWidth += $crumb.get(0).offsetWidth; + if (this.totalWidth > width) { + this.totalWidth -= $crumb.get(0).offsetWidth; + $crumb.addClass('hidden'); + break; + } + } + i--; + this.hiddenBreadcrumbs = i; + } + } + + this.lastWidth = width; + } + }; + + window.BreadCrumb = BreadCrumb; +})(); + diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 371c83e742cf75172d55e7b3bcba826d5364406c..e5d1eacbd149f2ad52db522e66ed71f0f701086e 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -180,7 +180,7 @@ OC.Upload = { }, init: function() { - if ( $('#file_upload_start').exists() && $('#file_upload_start').is(':visible')) { + if ( $('#file_upload_start').exists() ) { var file_upload_param = { dropZone: $('#content'), // restrict dropZone to content div @@ -483,28 +483,6 @@ OC.Upload = { $('#file_upload_start').attr('multiple', 'multiple'); } - //if the breadcrumb is to long, start by replacing foldernames with '...' except for the current folder - var crumb=$('div.crumb').first(); - while($('div.controls').height() > 40 && crumb.next('div.crumb').length > 0) { - crumb.children('a').text('...'); - crumb = crumb.next('div.crumb'); - } - //if that isn't enough, start removing items from the breacrumb except for the current folder and it's parent - var crumb = $('div.crumb').first(); - var next = crumb.next('div.crumb'); - while($('div.controls').height()>40 && next.next('div.crumb').length > 0) { - crumb.remove(); - crumb = next; - next = crumb.next('div.crumb'); - } - //still not enough, start shorting down the current folder name - var crumb=$('div.crumb>a').last(); - while($('div.controls').height() > 40 && crumb.text().length > 6) { - var text=crumb.text(); - text = text.substr(0,text.length-6)+'...'; - crumb.text(text); - } - $(document).click(function(ev) { // do not close when clicking in the dropdown if ($(ev.target).closest('#new').length){ @@ -617,21 +595,7 @@ OC.Upload = { {dir:$('#dir').val(), filename:name}, function(result) { if (result.status === 'success') { - var date = new Date(); - // TODO: ideally addFile should be able to receive - // all attributes and set them automatically, - // and also auto-load the preview - var tr = FileList.addFile(name, 0, date, false, hidden); - tr.attr('data-size', result.data.size); - tr.attr('data-mime', result.data.mime); - tr.attr('data-id', result.data.id); - tr.attr('data-etag', result.data.etag); - tr.find('.filesize').text(humanFileSize(result.data.size)); - var path = getPathForPreview(name); - Files.lazyLoadPreview(path, result.data.mime, function(previewpath) { - tr.find('td.filename').attr('style','background-image:url('+previewpath+')'); - }, null, null, result.data.etag); - FileActions.display(tr.find('td.filename'), true); + FileList.add(result.data, {hidden: hidden, insert: true}); } else { OC.dialogs.alert(result.data.message, t('core', 'Could not create file')); } @@ -644,10 +608,7 @@ OC.Upload = { {dir:$('#dir').val(), foldername:name}, function(result) { if (result.status === 'success') { - var date=new Date(); - FileList.addDir(name, 0, date, hidden); - var tr = FileList.findFileEl(name); - tr.attr('data-id', result.data.id); + FileList.add(result.data, {hidden: hidden, insert: true}); } else { OC.dialogs.alert(result.data.message, t('core', 'Could not create folder')); } @@ -682,20 +643,10 @@ OC.Upload = { } }); eventSource.listen('success',function(data) { - var mime = data.mime; - var size = data.size; - var id = data.id; + var file = data; $('#uploadprogressbar').fadeOut(); - var date = new Date(); - FileList.addFile(localName, size, date, false, hidden); - var tr = FileList.findFileEl(localName); - tr.data('mime', mime).data('id', id); - tr.attr('data-id', id); - var path = $('#dir').val()+'/'+localName; - Files.lazyLoadPreview(path, mime, function(previewpath) { - tr.find('td.filename').attr('style', 'background-image:url('+previewpath+')'); - }, null, null, data.etag); - FileActions.display(tr.find('td.filename'), true); + + FileList.add(file, {hidden: hidden, insert: true}); }); eventSource.listen('error',function(error) { $('#uploadprogressbar').fadeOut(); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 9a69d7b368869138bf05948894de9e0f28dbdad7..631aebea954d12d0319d242ea8cbeb9c18dd007f 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -8,28 +8,40 @@ * */ -/* global OC, FileList */ +/* global OC, FileList, Files */ /* global trashBinApp */ var FileActions = { actions: {}, defaults: {}, icons: {}, currentFile: null, - register: function (mime, name, permissions, icon, action) { + register: function (mime, name, permissions, icon, action, displayName) { if (!FileActions.actions[mime]) { FileActions.actions[mime] = {}; } if (!FileActions.actions[mime][name]) { FileActions.actions[mime][name] = {}; } + if (!displayName) { + displayName = t('files', name); + } FileActions.actions[mime][name]['action'] = action; FileActions.actions[mime][name]['permissions'] = permissions; + FileActions.actions[mime][name]['displayName'] = displayName; FileActions.icons[name] = icon; }, setDefault: function (mime, name) { FileActions.defaults[mime] = name; }, get: function (mime, type, permissions) { + var actions = this.getActions(mime, type, permissions); + var filteredActions = {}; + $.each(actions, function (name, action) { + filteredActions[name] = action.action; + }); + return filteredActions; + }, + getActions: function (mime, type, permissions) { var actions = {}; if (FileActions.actions.all) { actions = $.extend(actions, FileActions.actions.all); @@ -51,7 +63,7 @@ var FileActions = { var filteredActions = {}; $.each(actions, function (name, action) { if (action.permissions & permissions) { - filteredActions[name] = action.action; + filteredActions[name] = action; } }); return filteredActions; @@ -82,7 +94,7 @@ var FileActions = { */ display: function (parent, triggerEvent) { FileActions.currentFile = parent; - var actions = FileActions.get(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions()); + var actions = FileActions.getActions(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions()); var file = FileActions.getCurrentFile(); var nameLinks; if (FileList.findFileEl(file).data('renaming')) { @@ -105,15 +117,16 @@ var FileActions = { event.data.actionFunc(file); }; - var addAction = function (name, action) { + var addAction = function (name, action, displayName) { // NOTE: Temporary fix to prevent rename action in root of Shared directory if (name === 'Rename' && $('#dir').val() === '/Shared') { return true; } if ((name === 'Download' || action !== defaultAction) && name !== 'Delete') { + var img = FileActions.icons[name], - actionText = t('files', name), + actionText = displayName, actionContainer = 'a.name>span.fileactions'; if (name === 'Rename') { @@ -125,7 +138,7 @@ var FileActions = { if (img.call) { img = img(file); } - var html = ''; + var html = ''; if (img) { html += ''; } @@ -133,8 +146,7 @@ var FileActions = { var element = $(html); element.data('action', name); - //alert(element); - element.on('click', {a: null, elem: parent, actionFunc: actions[name]}, actionHandler); + element.on('click', {a: null, elem: parent, actionFunc: actions[name].action}, actionHandler); parent.find(actionContainer).append(element); } @@ -142,12 +154,15 @@ var FileActions = { $.each(actions, function (name, action) { if (name !== 'Share') { - addAction(name, action); + displayName = action.displayName; + ah = action.action; + + addAction(name, ah, displayName); } }); if(actions.Share && !($('#dir').val() === '/' && file === 'Shared')){ - // t('files', 'Share') - addAction('Share', actions.Share); + displayName = t('files', 'Share'); + addAction('Share', actions.Share, displayName); } // remove the existing delete action @@ -165,7 +180,7 @@ var FileActions = { } var element = $(html); element.data('action', actions['Delete']); - element.on('click', {a: null, elem: parent, actionFunc: actions['Delete']}, actionHandler); + element.on('click', {a: null, elem: parent, actionFunc: actions['Delete'].action}, actionHandler); parent.parent().children().last().append(element); } @@ -199,7 +214,7 @@ $(document).ready(function () { FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () { return OC.imagePath('core', 'actions/download'); }, function (filename) { - var url = FileList.getDownloadUrl(filename); + var url = Files.getDownloadUrl(filename); if (url) { OC.redirect(url); } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 503bf6811394453e9e0291338a1da1cae7ccc4f8..506741eb6eabee9d6498d3f9a15596d12591b55d 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -8,17 +8,104 @@ * */ -/* global OC, t, n, FileList, FileActions, Files */ -/* global procesSelection, dragOptions, SVGSupport, replaceSVG */ -window.FileList={ +/* global OC, t, n, FileList, FileActions, Files, BreadCrumb */ +/* global procesSelection, dragOptions */ +window.FileList = { appName: t('files', 'Files'), + isEmpty: true, useUndo:true, - postProcessList: function() { - $('#fileList tr').each(function() { - //little hack to set unescape filenames in attribute - $(this).attr('data-file',decodeURIComponent($(this).attr('data-file'))); + $el: $('#filestable'), + $fileList: $('#fileList'), + breadcrumb: null, + initialized: false, + + /** + * Initialize the file list and its components + */ + initialize: function() { + var self = this; + if (this.initialized) { + return; + } + + // TODO: FileList should not know about global elements + this.$el = $('#filestable'); + this.$fileList = $('#fileList'); + + this.breadcrumb = new BreadCrumb({ + onClick: this._onClickBreadCrumb, + onDrop: this._onDropOnBreadCrumb, + getCrumbUrl: function(part, index) { + return self.linkTo(part.dir); + } + }); + + $('#controls').prepend(this.breadcrumb.$el); + + $(window).resize(function() { + // TODO: debounce this ? + var width = $(this).width(); + FileList.breadcrumb.resize(width, false); }); }, + + /** + * Event handler when clicking on a bread crumb + */ + _onClickBreadCrumb: function(e) { + var $el = $(e.target).closest('.crumb'), + $targetDir = $el.data('dir'); + + if ($targetDir !== undefined) { + e.preventDefault(); + FileList.changeDirectory($targetDir); + } + }, + + /** + * Event handler when dropping on a breadcrumb + */ + _onDropOnBreadCrumb: function( event, ui ) { + var target=$(this).data('dir'); + var dir = FileList.getCurrentDirectory(); + while(dir.substr(0,1) === '/') {//remove extra leading /'s + dir=dir.substr(1); + } + dir = '/' + dir; + if (dir.substr(-1,1) !== '/') { + dir = dir + '/'; + } + if (target === dir || target+'/' === dir) { + return; + } + var files = ui.helper.find('tr'); + $(files).each(function(i,row) { + var dir = $(row).data('dir'); + var file = $(row).data('filename'); + //slapdash selector, tracking down our original element that the clone budded off of. + var origin = $('tr[data-id=' + $(row).data('origin') + ']'); + var td = origin.children('td.filename'); + var oldBackgroundImage = td.css('background-image'); + td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); + $.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: target }, function(result) { + if (result) { + if (result.status === 'success') { + FileList.remove(file); + procesSelection(); + $('#notification').hide(); + } else { + $('#notification').hide(); + $('#notification').text(result.data.message); + $('#notification').fadeIn(); + } + } else { + OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); + } + td.css('background-image', oldBackgroundImage); + }); + }); + }, + /** * Sets a new page title */ @@ -36,64 +123,117 @@ window.FileList={ }, /** * Returns the tr element for a given file name + * @param fileName file name */ findFileEl: function(fileName){ // use filterAttr to avoid escaping issues - return $('#fileList tr').filterAttr('data-file', fileName); + return this.$fileList.find('tr').filterAttr('data-file', fileName); }, - update:function(fileListHtml) { - var $fileList = $('#fileList'); - $fileList.empty().html(fileListHtml); - FileList.updateEmptyContent(); - $fileList.find('tr').each(function () { - FileActions.display($(this).children('td.filename')); - }); - $fileList.trigger(jQuery.Event("fileActionsReady")); - FileList.postProcessList(); + /** + * Sets the files to be displayed in the list. + * This operation will rerender the list and update the summary. + * @param filesArray array of file data (map) + */ + setFiles:function(filesArray) { + // detach to make adding multiple rows faster + this.$fileList.detach(); + + this.$fileList.empty(); + + this.isEmpty = filesArray.length === 0; + for (var i = 0; i < filesArray.length; i++) { + this.add(filesArray[i], {updateSummary: false}); + } + + this.$el.find('thead').after(this.$fileList); + + this.updateEmptyContent(); + this.$fileList.trigger(jQuery.Event("fileActionsReady")); // "Files" might not be loaded in extending apps if (window.Files) { Files.setupDragAndDrop(); } - FileList.updateFileSummary(); + this.updateFileSummary(); procesSelection(); - $(window).scrollTop(0); - $fileList.trigger(jQuery.Event("updated")); + + this.$fileList.trigger(jQuery.Event("updated")); }, - createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions) { - var td, simpleSize, basename, extension; + /** + * Creates a new table row element using the given file data. + * @param fileData map of file attributes + * @param options map of attribute "loading" whether the entry is currently loading + * @return new tr element (not appended to the table) + */ + _createRow: function(fileData, options) { + var td, simpleSize, basename, extension, sizeColor, + icon = OC.Util.replaceSVGIcon(fileData.icon), + name = fileData.name, + type = fileData.type || 'file', + mtime = parseInt(fileData.mtime, 10) || new Date().getTime(), + mime = fileData.mimetype, + linkUrl; + options = options || {}; + + if (type === 'dir') { + mime = mime || 'httpd/unix-directory'; + } //containing tr var tr = $('').attr({ + "data-id" : fileData.id, "data-type": type, - "data-size": size, + "data-size": fileData.size, "data-file": name, - "data-permissions": permissions + "data-mime": mime, + "data-mtime": mtime, + "data-etag": fileData.etag, + "data-permissions": fileData.permissions || this.getDirectoryPermissions() }); + + if (type === 'dir') { + // use default folder icon + icon = icon || OC.imagePath('core', 'filetypes/folder'); + } + else { + icon = icon || OC.imagePath('core', 'filetypes/file'); + } + // filename td td = $('').attr({ "class": "filename", - "style": 'background-image:url('+iconurl+'); background-size: 32px;' + "style": 'background-image:url(' + icon + '); background-size: 32px;' }); - var rand = Math.random().toString(16).slice(2); - td.append(''); + + // linkUrl + if (type === 'dir') { + linkUrl = FileList.linkTo(FileList.getCurrentDirectory() + '/' + name); + } + else { + linkUrl = Files.getDownloadUrl(name, FileList.getCurrentDirectory()); + } + td.append(''); var link_elem = $('').attr({ "class": "name", - "href": linktarget + "href": linkUrl }); - //split extension from filename for non dirs + + // from here work on the display name + name = fileData.displayName || name; + + // split extension from filename for non dirs if (type !== 'dir' && name.indexOf('.') !== -1) { - basename=name.substr(0,name.lastIndexOf('.')); - extension=name.substr(name.lastIndexOf('.')); + basename = name.substr(0, name.lastIndexOf('.')); + extension = name.substr(name.lastIndexOf('.')); } else { - basename=name; - extension=false; + basename = name; + extension = false; } var name_span=$('').addClass('nametext').text(basename); link_elem.append(name_span); if (extension) { name_span.append($('').addClass('extension').text(extension)); } - //dirs can show the number of uploaded files + // dirs can show the number of uploaded files if (type === 'dir') { link_elem.append($('').attr({ 'class': 'uploadtext', @@ -103,98 +243,122 @@ window.FileList={ td.append(link_elem); tr.append(td); - //size column - if (size !== t('files', 'Pending')) { - simpleSize = humanFileSize(size); + // size column + if (typeof(fileData.size) !== 'undefined' && fileData.size >= 0) { + simpleSize = humanFileSize(parseInt(fileData.size, 10)); + sizeColor = Math.round(160-Math.pow((fileData.size/(1024*1024)),2)); } else { - simpleSize=t('files', 'Pending'); + simpleSize = t('files', 'Pending'); } - var sizeColor = Math.round(160-Math.pow((size/(1024*1024)),2)); - var lastModifiedTime = Math.round(lastModified.getTime() / 1000); + var lastModifiedTime = Math.round(mtime / 1000); td = $('').attr({ "class": "filesize", - "style": 'color:rgb('+sizeColor+','+sizeColor+','+sizeColor+')' + "style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')' }).text(simpleSize); tr.append(td); // date column - var modifiedColor = Math.round((Math.round((new Date()).getTime() / 1000)-lastModifiedTime)/60/60/24*5); + var modifiedColor = Math.round((Math.round((new Date()).getTime() / 1000) - mtime)/60/60/24*5); td = $('').attr({ "class": "date" }); td.append($('').attr({ "class": "modified", - "title": formatDate(lastModified), + "title": formatDate(mtime), "style": 'color:rgb('+modifiedColor+','+modifiedColor+','+modifiedColor+')' - }).text( relative_modified_date(lastModified.getTime() / 1000) )); + }).text( relative_modified_date(mtime / 1000) )); + tr.find('.filesize').text(simpleSize); tr.append(td); return tr; }, - addFile:function(name, size, lastModified, loading, hidden, param) { - var imgurl; + /** + * Adds an entry to the files table using the data from the given file data + * @param fileData map of file attributes + * @param options map of attributes: + * - "insert" true to insert in a sorted manner, false to append (default) + * - "updateSummary" true to update the summary after adding (default), false otherwise + * @return new tr element (not appended to the table) + */ + add: function(fileData, options) { + options = options || {}; + var type = fileData.type || 'file', + mime = fileData.mimetype, + permissions = parseInt(fileData.permissions, 10) || 0; - if (!param) { - param = {}; + if (type === 'dir') { + mime = mime || 'httpd/unix-directory'; } + var tr = this._createRow( + fileData, + options + ); + var filenameTd = tr.find('td.filename'); - var download_url = null; - if (!param.download_url) { - download_url = OC.generateUrl( - 'apps/files/download{file}', - { file: $('#dir').val()+'/'+name }); - } else { - download_url = param.download_url; + // sorted insert is expensive, so needs to be explicitly + // requested + if (options.insert) { + this.insertElement(fileData.name, type, tr); } + else { + this.$fileList.append(tr); + } + FileList.isEmpty = false; - if (loading) { - imgurl = OC.imagePath('core', 'loading.gif'); - } else { - imgurl = OC.imagePath('core', 'filetypes/file'); - } - var tr = this.createRow( - 'file', - name, - imgurl, - download_url, - size, - lastModified, - $('#permissions').val() - ); + // TODO: move dragging to FileActions ? + // enable drag only for deletable files + if (permissions & OC.PERMISSION_DELETE) { + filenameTd.draggable(dragOptions); + } + // allow dropping on folders + if (fileData.type === 'dir') { + filenameTd.droppable(folderDropOptions); + } - FileList.insertElement(name, 'file', tr); - if (loading) { - tr.data('loading', true); - } else { - tr.find('td.filename').draggable(dragOptions); + if (options.hidden) { + tr.addClass('hidden'); } - if (hidden) { - tr.hide(); + + // display actions + FileActions.display(filenameTd, false); + + if (fileData.isPreviewAvailable) { + // lazy load / newly inserted td ? + if (!fileData.icon) { + Files.lazyLoadPreview(getPathForPreview(fileData.name), mime, function(url) { + filenameTd.css('background-image', 'url(' + url + ')'); + }, null, null, fileData.etag); + } + else { + // set the preview URL directly + var urlSpec = { + file: FileList.getCurrentDirectory() + '/' + fileData.name, + c: fileData.etag + }; + var previewUrl = Files.generatePreviewUrl(urlSpec); + previewUrl = previewUrl.replace('(', '%28').replace(')', '%29'); + filenameTd.css('background-image', 'url(' + previewUrl + ')'); + } } - return tr; - }, - addDir:function(name, size, lastModified, hidden) { - - var tr = this.createRow( - 'dir', - name, - OC.imagePath('core', 'filetypes/folder'), - OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent($('#dir').val()+'/'+name).replace(/%2F/g, '/'), - size, - lastModified, - $('#permissions').val() - ); - FileList.insertElement(name, 'dir', tr); - var td = tr.find('td.filename'); - td.draggable(dragOptions); - td.droppable(folderDropOptions); - if (hidden) { - tr.hide(); + // defaults to true if not defined + if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) { + this.updateFileSummary(); + this.updateEmptyContent(); } - FileActions.display(tr.find('td.filename'), true); return tr; }, + /** + * Returns the current directory + * @return current directory + */ getCurrentDirectory: function(){ return $('#dir').val() || '/'; }, + /** + * Returns the directory permissions + * @return permission value as integer + */ + getDirectoryPermissions: function() { + return parseInt($('#permissions').val(), 10); + }, /** * @brief Changes the current directory and reload the file list. * @param targetDir target directory (non URL encoded) @@ -209,7 +373,7 @@ window.FileList={ if (!force && currentDir === targetDir) { return; } - FileList.setCurrentDir(targetDir, changeUrl); + FileList._setCurrentDir(targetDir, changeUrl); $('#fileList').trigger( jQuery.Event('changeDirectory', { dir: targetDir, @@ -221,7 +385,13 @@ window.FileList={ linkTo: function(dir) { return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); }, - setCurrentDir: function(targetDir, changeUrl) { + + /** + * Sets the current directory name and updates the breadcrumb. + * @param targetDir directory to display + * @param changeUrl true to also update the URL, false otherwise (default) + */ + _setCurrentDir: function(targetDir, changeUrl) { var url, baseDir = OC.basename(targetDir); @@ -243,6 +413,7 @@ window.FileList={ window.location.hash = '?dir='+ encodeURIComponent(targetDir).replace(/%2F/g, '/'); } } + this.breadcrumb.setDirectory(this.getCurrentDirectory()); }, /** * @brief Reloads the file list using ajax call @@ -253,10 +424,9 @@ window.FileList={ FileList._reloadCall.abort(); } FileList._reloadCall = $.ajax({ - url: OC.filePath('files','ajax','list.php'), + url: Files.getAjaxUrl('list'), data: { - dir : $('#dir').val(), - breadcrumb: true + dir : $('#dir').val() }, error: function(result) { FileList.reloadCallback(result); @@ -269,8 +439,8 @@ window.FileList={ reloadCallback: function(result) { var $controls = $('#controls'); - delete FileList._reloadCall; - FileList.hideMask(); + delete this._reloadCall; + this.hideMask(); if (!result || result.status === 'error') { OC.Notification.show(result.data.message); @@ -279,7 +449,11 @@ window.FileList={ if (result.status === 404) { // go back home - FileList.changeDirectory('/'); + this.changeDirectory('/'); + return; + } + // aborted ? + if (result.status === 0){ return; } @@ -288,24 +462,10 @@ window.FileList={ Files.updateStorageStatistics(true); if (result.data.permissions) { - FileList.setDirectoryPermissions(result.data.permissions); + this.setDirectoryPermissions(result.data.permissions); } - if (typeof(result.data.breadcrumb) !== 'undefined') { - $controls.find('.crumb').remove(); - $controls.prepend(result.data.breadcrumb); - - var width = $(window).width(); - Files.initBreadCrumbs(); - Files.resizeBreadcrumbs(width, true); - - // in case svg is not supported by the browser we need to execute the fallback mechanism - if (!SVGSupport()) { - replaceSVG(); - } - } - - FileList.update(result.data.files); + this.setFiles(result.data.files); }, setDirectoryPermissions: function(permissions) { var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; @@ -322,10 +482,14 @@ window.FileList={ $('.actions,#file_action_panel').toggleClass('hidden', !show); if (show){ // make sure to display according to permissions - var permissions = $('#permissions').val(); + var permissions = this.getDirectoryPermissions(); var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; $('.creatable').toggleClass('hidden', !isCreatable); $('.notCreatable').toggleClass('hidden', isCreatable); + // remove old style breadcrumbs (some apps might create them) + $('#controls .crumb').remove(); + // refresh breadcrumbs in case it was replaced by an app + this.breadcrumb.render(); } else{ $('.creatable, .notCreatable').addClass('hidden'); @@ -341,22 +505,32 @@ window.FileList={ this.showActions(!show); $('#filestable').toggleClass('hidden', show); }, - remove:function(name){ + /** + * Removes a file entry from the list + * @param name name of the file to remove + * @param options optional options as map: + * "updateSummary": true to update the summary (default), false otherwise + */ + remove:function(name, options){ + options = options || {}; var fileEl = FileList.findFileEl(name); if (fileEl.data('permissions') & OC.PERMISSION_DELETE) { // file is only draggable when delete permissions are set fileEl.find('td.filename').draggable('destroy'); } fileEl.remove(); - FileList.updateFileSummary(); - if ( ! $('tr[data-file]').exists() ) { - $('#emptycontent').removeClass('hidden'); - $('#filescontent th').addClass('hidden'); + // TODO: improve performance on batch update + FileList.isEmpty = !this.$fileList.find('tr:not(.summary)').length; + if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) { + FileList.updateEmptyContent(); + FileList.updateFileSummary(); } + return fileEl; }, insertElement:function(name, type, element) { - //find the correct spot to insert the file or folder - var pos, fileElements=$('tr[data-file][data-type="'+type+'"]:visible'); + // find the correct spot to insert the file or folder + var pos, + fileElements = this.$fileList.find('tr[data-file][data-type="'+type+'"]:not(.hidden)'); if (name.localeCompare($(fileElements[0]).attr('data-file')) < 0) { pos = -1; } else if (name.localeCompare($(fileElements[fileElements.length-1]).attr('data-file')) > 0) { @@ -376,35 +550,18 @@ window.FileList={ } else { $(fileElements[pos]).after(element); } - } else if (type === 'dir' && $('tr[data-file]').exists()) { - $('tr[data-file]').first().before(element); - } else if (type === 'file' && $('tr[data-file]').exists()) { - $('tr[data-file]').last().before(element); + } else if (type === 'dir' && !FileList.isEmpty) { + this.$fileList.find('tr[data-file]:first').before(element); + } else if (type === 'file' && !FileList.isEmpty) { + this.$fileList.find('tr[data-file]:last').before(element); } else { - $('#fileList').append(element); + this.$fileList.append(element); } - $('#emptycontent').addClass('hidden'); - $('#filestable th').removeClass('hidden'); + FileList.isEmpty = false; + FileList.updateEmptyContent(); FileList.updateFileSummary(); }, - loadingDone:function(name, id) { - var mime, tr = FileList.findFileEl(name); - tr.data('loading', false); - mime = tr.data('mime'); - tr.attr('data-mime', mime); - if (id) { - tr.attr('data-id', id); - } - var path = getPathForPreview(name); - Files.lazyLoadPreview(path, mime, function(previewpath) { - tr.find('td.filename').attr('style','background-image:url('+previewpath+')'); - }, null, null, tr.attr('data-etag')); - tr.find('td.filename').draggable(dragOptions); - }, - isLoading:function(file) { - return FileList.findFileEl(file).data('loading'); - }, - rename:function(oldname) { + rename: function(oldname) { var tr, td, input, form; tr = FileList.findFileEl(oldname); tr.data('renaming',true); @@ -438,6 +595,7 @@ window.FileList={ event.preventDefault(); try { var newname = input.val(); + var directory = FileList.getCurrentDirectory(); if (newname !== oldname) { checkInput(); // save background image, because it's replaced by a spinner while async request @@ -480,12 +638,16 @@ window.FileList={ tr.attr('data-mime', fileInfo.mime); tr.attr('data-etag', fileInfo.etag); if (fileInfo.isPreviewAvailable) { - Files.lazyLoadPreview(fileInfo.directory + '/' + fileInfo.name, result.data.mime, function(previewpath) { + Files.lazyLoadPreview(directory + '/' + fileInfo.name, result.data.mime, function(previewpath) { tr.find('td.filename').attr('style','background-image:url('+previewpath+')'); }, null, null, result.data.etag); } else { - tr.find('td.filename').removeClass('preview').attr('style','background-image:url('+fileInfo.icon+')'); + tr.find('td.filename') + .removeClass('preview') + .attr('style','background-image:url(' + + OC.Util.replaceSVGIcon(fileInfo.icon) + + ')'); } } // reinsert row @@ -554,58 +716,12 @@ window.FileList={ inList:function(file) { return FileList.findFileEl(file).length; }, - replace:function(oldName, newName, isNewFile) { - // Finish any existing actions - var oldFileEl = FileList.findFileEl(oldName); - var newFileEl = FileList.findFileEl(newName); - oldFileEl.hide(); - newFileEl.hide(); - var tr = oldFileEl.clone(); - tr.attr('data-replace', 'true'); - tr.attr('data-file', newName); - var td = tr.children('td.filename'); - td.children('a.name .span').text(newName); - var path = td.children('a.name').attr('href'); - td.children('a.name').attr('href', path.replace(encodeURIComponent(oldName), encodeURIComponent(newName))); - var basename = newName; - if (newName.indexOf('.') > 0) { - basename = newName.substr(0, newName.lastIndexOf('.')); - } - td.children('a.name').empty(); - var span = $(''); - span.text(basename); - td.children('a.name').append(span); - if (newName.indexOf('.') > 0) { - span.append($(''+newName.substr(newName.lastIndexOf('.'))+'')); - } - FileList.insertElement(newName, tr.data('type'), tr); - tr.show(); - FileList.replaceCanceled = false; - FileList.replaceOldName = oldName; - FileList.replaceNewName = newName; - FileList.replaceIsNewFile = isNewFile; - FileList.lastAction = function() { - FileList.finishReplace(); - }; - if (!isNewFile) { - OC.Notification.showHtml(t('files', 'replaced {new_name} with {old_name}', {new_name: newName}, {old_name: oldName})+''+t('files', 'undo')+''); - } - }, - finishReplace:function() { - if (!FileList.replaceCanceled && FileList.replaceOldName && FileList.replaceNewName) { - $.ajax({url: OC.filePath('files', 'ajax', 'rename.php'), async: false, data: { dir: $('#dir').val(), newname: FileList.replaceNewName, file: FileList.replaceOldName }, success: function(result) { - if (result && result.status === 'success') { - $('tr[data-replace="true"').removeAttr('data-replace'); - } else { - OC.dialogs.alert(result.data.message, 'Error moving file'); - } - FileList.replaceCanceled = true; - FileList.replaceOldName = null; - FileList.replaceNewName = null; - FileList.lastAction = null; - }}); - } - }, + /** + * Delete the given files from the given dir + * @param files file names list (without path) + * @param dir directory in which to delete the files, defaults to the current + * directory + */ do_delete:function(files, dir) { var params; if (files && files.substr) { @@ -622,7 +738,7 @@ window.FileList={ FileList.lastAction(); } - var params = { + params = { dir: dir || FileList.getCurrentDirectory() }; if (files) { @@ -643,10 +759,9 @@ window.FileList={ } else { $.each(files,function(index,file) { - var files = FileList.findFileEl(file); - files.remove(); - files.find('input[type="checkbox"]').removeAttr('checked'); - files.removeClass('selected'); + var fileEl = FileList.remove(file, {updateSummary: false}); + fileEl.find('input[type="checkbox"]').prop('checked', false); + fileEl.removeClass('selected'); }); } procesSelection(); @@ -680,7 +795,7 @@ window.FileList={ }); }, createFileSummary: function() { - if( $('#fileList tr').exists() ) { + if ( !FileList.isEmpty ) { var summary = this._calculateFileSummary(); // Get translations @@ -702,7 +817,7 @@ window.FileList={ } var $summary = $(''+info+''+fileSize+''); - $('#fileList').append($summary); + this.$fileList.append($summary); var $dirInfo = $summary.find('.dirinfo'); var $fileInfo = $summary.find('.fileinfo'); @@ -710,12 +825,12 @@ window.FileList={ // Show only what's necessary, e.g.: no files: don't show "0 files" if (summary.totalDirs === 0) { - $dirInfo.hide(); - $connector.hide(); + $dirInfo.addClass('hidden'); + $connector.addClass('hidden'); } if (summary.totalFiles === 0) { - $fileInfo.hide(); - $connector.hide(); + $fileInfo.addClass('hidden'); + $connector.addClass('hidden'); } } }, @@ -740,10 +855,13 @@ window.FileList={ return result; }, updateFileSummary: function() { - var $summary = $('.summary'); + var $summary = this.$el.find('.summary'); + + // always make it the last element + this.$fileList.append($summary.detach()); // Check if we should remove the summary to show "Upload something" - if ($('#fileList tr').length === 1 && $summary.length === 1) { + if (this.isEmpty && $summary.length === 1) { $summary.remove(); } // If there's no summary create one (createFileSummary checks if there's data) @@ -751,7 +869,7 @@ window.FileList={ FileList.createFileSummary(); } // There's a summary and data -> Update the summary - else if ($('#fileList tr').length > 1 && $summary.length === 1) { + else if (!this.isEmpty && $summary.length === 1) { var fileSummary = this._calculateFileSummary(); var $dirInfo = $('.summary .dirinfo'); var $fileInfo = $('.summary .fileinfo'); @@ -764,19 +882,19 @@ window.FileList={ // Show only what's necessary (may be hidden) if (fileSummary.totalDirs === 0) { - $dirInfo.hide(); - $connector.hide(); + $dirInfo.addClass('hidden'); + $connector.addClass('hidden'); } else { - $dirInfo.show(); + $dirInfo.removeClass('hidden'); } if (fileSummary.totalFiles === 0) { - $fileInfo.hide(); - $connector.hide(); + $fileInfo.addClass('hidden'); + $connector.addClass('hidden'); } else { - $fileInfo.show(); + $fileInfo.removeClass('hidden'); } if (fileSummary.totalDirs > 0 && fileSummary.totalFiles > 0) { - $connector.show(); + $connector.removeClass('hidden'); } } }, @@ -784,10 +902,14 @@ window.FileList={ var $fileList = $('#fileList'); var permissions = $('#permissions').val(); var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; - var exists = $fileList.find('tr:first').exists(); - $('#emptycontent').toggleClass('hidden', !isCreatable || exists); - $('#filestable th').toggleClass('hidden', !exists); + $('#emptycontent').toggleClass('hidden', !isCreatable || !FileList.isEmpty); + $('#filestable thead th').toggleClass('hidden', FileList.isEmpty); }, + /** + * Shows the loading mask. + * + * @see #hideMask + */ showMask: function() { // in case one was shown before var $mask = $('#content .mask'); @@ -795,23 +917,23 @@ window.FileList={ return; } + this.$el.addClass('hidden'); + $mask = $('
'); $mask.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); $mask.css('background-repeat', 'no-repeat'); $('#content').append($mask); - // block UI, but only make visible in case loading takes longer - FileList._maskTimeout = window.setTimeout(function() { - // reset opacity - $mask.removeClass('transparent'); - }, 250); + $mask.removeClass('transparent'); }, + /** + * Hide the loading mask. + * @see #showMask + */ hideMask: function() { - var $mask = $('#content .mask').remove(); - if (FileList._maskTimeout) { - window.clearTimeout(FileList._maskTimeout); - } + $('#content .mask').remove(); + this.$el.removeClass('hidden'); }, scrollTo:function(file) { //scroll to and highlight preselected file @@ -850,29 +972,11 @@ window.FileList={ */ isAllSelected: function() { return $('#select_all').prop('checked'); - }, - - /** - * Returns the download URL of the given file - * @param filename file name of the file - * @param dir optional directory in which the file name is, defaults to the current directory - */ - getDownloadUrl: function(filename, dir) { - var files = filename; - if ($.isArray(filename)) { - files = JSON.stringify(filename); - } - var params = { - dir: dir || FileList.getCurrentDirectory(), - files: files - }; - return OC.filePath('files', 'ajax', 'download.php') + '?' + OC.buildQueryString(params); } }; $(document).ready(function() { - var baseDir, - isPublic = !!$('#isPublic').val(); + FileList.initialize(); // handle upload events var file_upload_start = $('#file_upload_start'); @@ -907,8 +1011,13 @@ $(document).ready(function() { {name: 'requesttoken', value: oc_requesttoken} ]; }; + } else { + // cancel uploads to current dir if no permission + var isCreatable = (FileList.getDirectoryPermissions() & OC.PERMISSION_CREATE) !== 0; + if (!isCreatable) { + return false; + } } - }); file_upload_start.on('fileuploadadd', function(e, data) { OC.Upload.log('filelist handle fileuploadadd', e, data); @@ -993,31 +1102,11 @@ $(document).ready(function() { if (data.files[0].size>=0) { size=data.files[0].size; } - var date=new Date(); - var param = {}; - if ($('#publicUploadRequestToken').exists()) { - param.download_url = document.location.href + '&download&path=/' + $('#dir').val() + '/' + file.name; - } //should the file exist in the list remove it FileList.remove(file.name); // create new file context - data.context = FileList.addFile(file.name, file.size, date, false, false, param); - - // update file data - data.context.attr('data-mime',file.mime).attr('data-id',file.id).attr('data-etag', file.etag); - - var permissions = data.context.data('permissions'); - if (permissions !== file.permissions) { - data.context.attr('data-permissions', file.permissions); - data.context.data('permissions', file.permissions); - } - FileActions.display(data.context.find('td.filename'), true); - - var path = getPathForPreview(file.name); - Files.lazyLoadPreview(path, file.mime, function(previewpath) { - data.context.find('td.filename').attr('style','background-image:url('+previewpath+')'); - }, null, null, file.etag); + data.context = FileList.add(file, {insert: true}); } } }); @@ -1049,31 +1138,6 @@ $(document).ready(function() { }); $('#notification').hide(); - $('#notification').on('click', '.undo', function() { - if (FileList.deleteFiles) { - $.each(FileList.deleteFiles,function(index,file) { - FileList.findFileEl(file).show(); - }); - FileList.deleteCanceled=true; - FileList.deleteFiles=null; - } else if (FileList.replaceOldName && FileList.replaceNewName) { - if (FileList.replaceIsNewFile) { - // Delete the new uploaded file - FileList.deleteCanceled = false; - FileList.deleteFiles = [FileList.replaceOldName]; - } else { - FileList.findFileEl(FileList.replaceOldName).show(); - } - $('tr[data-replace="true"').remove(); - FileList.findFileEl(FileList.replaceNewName).show(); - FileList.replaceCanceled = true; - FileList.replaceOldName = null; - FileList.replaceNewName = null; - FileList.replaceIsNewFile = null; - } - FileList.lastAction = null; - OC.Notification.hide(); - }); $('#notification:first-child').on('click', '.replace', function() { OC.Notification.hide(function() { FileList.replace($('#notification > span').attr('data-oldName'), $('#notification > span').attr('data-newName'), $('#notification > span').attr('data-isNewFile')); @@ -1081,7 +1145,7 @@ $(document).ready(function() { }); $('#notification:first-child').on('click', '.suggest', function() { var file = $('#notification > span').attr('data-oldName'); - FileList.findFileEl(file).show(); + FileList.findFileEl(file).removeClass('hidden'); OC.Notification.hide(); }); $('#notification:first-child').on('click', '.cancel', function() { @@ -1130,34 +1194,32 @@ $(document).ready(function() { } // disable ajax/history API for public app (TODO: until it gets ported) - if (!isPublic) { - // fallback to hashchange when no history support - if (!window.history.pushState) { - $(window).on('hashchange', function() { - FileList.changeDirectory(parseCurrentDirFromUrl(), false); - }); + // fallback to hashchange when no history support + if (!window.history.pushState) { + $(window).on('hashchange', function() { + FileList.changeDirectory(parseCurrentDirFromUrl(), false); + }); + } + window.onpopstate = function(e) { + var targetDir; + if (e.state && e.state.dir) { + targetDir = e.state.dir; } - window.onpopstate = function(e) { - var targetDir; - if (e.state && e.state.dir) { - targetDir = e.state.dir; - } - else{ - // read from URL - targetDir = parseCurrentDirFromUrl(); - } - if (targetDir) { - FileList.changeDirectory(targetDir, false); - } - }; - - if (parseInt($('#ajaxLoad').val(), 10) === 1) { - // need to initially switch the dir to the one from the hash (IE8) - FileList.changeDirectory(parseCurrentDirFromUrl(), false, true); + else{ + // read from URL + targetDir = parseCurrentDirFromUrl(); + } + if (targetDir) { + FileList.changeDirectory(targetDir, false); } + }; - FileList.setCurrentDir(parseCurrentDirFromUrl(), false); - } + var dir = parseCurrentDirFromUrl(); + // trigger ajax load, deferred to let sub-apps do their overrides first + setTimeout(function() { + FileList.changeDirectory(dir, false, true); + }, 0); FileList.createFileSummary(); }); + diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 1186a72a44f4cab38544409f4b1c9b8998954e3d..ac10191618b1adaa4e15a0778e5b0b9d319254fb 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -131,15 +131,15 @@ var Files = { var encryptedFiles = $('#encryptedFiles').val(); var initStatus = $('#encryptionInitStatus').val(); if (initStatus === '0') { // enc not initialized, but should be - OC.Notification.show(t('files_encryption', 'Encryption App is enabled but your keys are not initialized, please log-out and log-in again')); + OC.Notification.show(t('files', 'Encryption App is enabled but your keys are not initialized, please log-out and log-in again')); return; } if (initStatus === '1') { // encryption tried to init but failed - OC.Notification.showHtml(t('files_encryption', 'Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files.')); + OC.Notification.showHtml(t('files', 'Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files.')); return; } if (encryptedFiles === '1') { - OC.Notification.show(t('files_encryption', 'Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.')); + OC.Notification.show(t('files', 'Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.')); return; } }, @@ -161,77 +161,33 @@ var Files = { }); }, - lastWidth: 0, - - initBreadCrumbs: function () { - var $controls = $('#controls'); - - Files.lastWidth = 0; - Files.breadcrumbs = []; - - // initialize with some extra space - Files.breadcrumbsWidth = 64; - if ( document.getElementById("navigation") ) { - Files.breadcrumbsWidth += $('#navigation').get(0).offsetWidth; + /** + * Returns the download URL of the given file(s) + * @param filename string or array of file names to download + * @param dir optional directory in which the file name is, defaults to the current directory + */ + getDownloadUrl: function(filename, dir) { + if ($.isArray(filename)) { + filename = JSON.stringify(filename); } - Files.hiddenBreadcrumbs = 0; - - $.each($('.crumb'), function(index, breadcrumb) { - Files.breadcrumbs[index] = breadcrumb; - Files.breadcrumbsWidth += $(breadcrumb).get(0).offsetWidth; - }); - - $.each($('#controls .actions>div'), function(index, action) { - Files.breadcrumbsWidth += $(action).get(0).offsetWidth; - }); - - // event handlers for breadcrumb items - $controls.find('.crumb a').on('click', onClickBreadcrumb); - - // setup drag and drop - $controls.find('.crumb:not(.last)').droppable(crumbDropOptions); + var params = { + dir: dir || FileList.getCurrentDirectory(), + files: filename + }; + return this.getAjaxUrl('download', params); }, - resizeBreadcrumbs: function (width, firstRun) { - if (width !== Files.lastWidth) { - if ((width < Files.lastWidth || firstRun) && width < Files.breadcrumbsWidth) { - if (Files.hiddenBreadcrumbs === 0) { - Files.breadcrumbsWidth -= $(Files.breadcrumbs[1]).get(0).offsetWidth; - $(Files.breadcrumbs[1]).find('a').hide(); - $(Files.breadcrumbs[1]).append('...'); - Files.breadcrumbsWidth += $(Files.breadcrumbs[1]).get(0).offsetWidth; - Files.hiddenBreadcrumbs = 2; - } - var i = Files.hiddenBreadcrumbs; - while (width < Files.breadcrumbsWidth && i > 1 && i < Files.breadcrumbs.length - 1) { - Files.breadcrumbsWidth -= $(Files.breadcrumbs[i]).get(0).offsetWidth; - $(Files.breadcrumbs[i]).hide(); - Files.hiddenBreadcrumbs = i; - i++; - } - } else if (width > Files.lastWidth && Files.hiddenBreadcrumbs > 0) { - var i = Files.hiddenBreadcrumbs; - while (width > Files.breadcrumbsWidth && i > 0) { - if (Files.hiddenBreadcrumbs === 1) { - Files.breadcrumbsWidth -= $(Files.breadcrumbs[1]).get(0).offsetWidth; - $(Files.breadcrumbs[1]).find('span').remove(); - $(Files.breadcrumbs[1]).find('a').show(); - Files.breadcrumbsWidth += $(Files.breadcrumbs[1]).get(0).offsetWidth; - } else { - $(Files.breadcrumbs[i]).show(); - Files.breadcrumbsWidth += $(Files.breadcrumbs[i]).get(0).offsetWidth; - if (Files.breadcrumbsWidth > width) { - Files.breadcrumbsWidth -= $(Files.breadcrumbs[i]).get(0).offsetWidth; - $(Files.breadcrumbs[i]).hide(); - break; - } - } - i--; - Files.hiddenBreadcrumbs = i; - } - } - Files.lastWidth = width; + /** + * Returns the ajax URL for a given action + * @param action action string + * @param params optional params map + */ + getAjaxUrl: function(action, params) { + var q = ''; + if (params) { + q = '?' + OC.buildQueryString(params); } + return OC.filePath('files', 'ajax', action + '.php') + q; } }; $(document).ready(function() { @@ -242,14 +198,10 @@ $(document).ready(function() { Files.displayEncryptionWarning(); Files.bindKeyboardShortcuts(document, jQuery); - FileList.postProcessList(); Files.setupDragAndDrop(); $('#file_action_panel').attr('activeAction', false); - // allow dropping on the "files" app icon - $('ul#apps li:first-child').data('dir','').droppable(crumbDropOptions); - // Triggers invisible file input $('#upload a').on('click', function() { $(this).parent().children('#file_upload_start').trigger('click'); @@ -308,7 +260,7 @@ $(document).ready(function() { var filename=$(this).parent().parent().attr('data-file'); var tr = FileList.findFileEl(filename); var renaming=tr.data('renaming'); - if (!renaming && !FileList.isLoading(filename)) { + if (!renaming) { FileActions.currentFile = $(this).parent(); var mime=FileActions.getCurrentMimeType(); var type=FileActions.getCurrentType(); @@ -374,15 +326,15 @@ $(document).ready(function() { dir = OC.dirname(dir) || '/'; } else { - files = getSelectedFilesTrash('name'); + files = Files.getSelectedFiles('name'); } OC.Notification.show(t('files','Your download is being prepared. This might take some time if the files are big.')); - OC.redirect(FileList.getDownloadUrl(files, dir)); + OC.redirect(Files.getDownloadUrl(files, dir)); return false; }); $('.delete-selected').click(function(event) { - var files=getSelectedFilesTrash('name'); + var files = Files.getSelectedFiles('name'); event.preventDefault(); if (FileList.isAllSelected()) { files = null; @@ -400,16 +352,6 @@ $(document).ready(function() { //do a background scan if needed scanFiles(); - Files.initBreadCrumbs(); - - $(window).resize(function() { - var width = $(this).width(); - Files.resizeBreadcrumbs(width, false); - }); - - var width = $(this).width(); - Files.resizeBreadcrumbs(width, true); - // display storage warnings setTimeout(Files.displayStorageWarnings, 100); OC.Notification.setDefault(Files.displayStorageWarnings); @@ -500,7 +442,7 @@ var createDragShadow = function(event) { $(event.target).parents('tr').find('td input:first').prop('checked',true); } - var selectedFiles = getSelectedFilesTrash(); + var selectedFiles = Files.getSelectedFiles(); if (!isDragSelected && selectedFiles.length === 1) { //revert the selection @@ -616,52 +558,8 @@ var folderDropOptions={ tolerance: 'pointer' }; -var crumbDropOptions={ - drop: function( event, ui ) { - var target=$(this).data('dir'); - var dir = $('#dir').val(); - while(dir.substr(0,1) === '/') {//remove extra leading /'s - dir=dir.substr(1); - } - dir = '/' + dir; - if (dir.substr(-1,1) !== '/') { - dir = dir + '/'; - } - if (target === dir || target+'/' === dir) { - return; - } - var files = ui.helper.find('tr'); - $(files).each(function(i,row) { - var dir = $(row).data('dir'); - var file = $(row).data('filename'); - //slapdash selector, tracking down our original element that the clone budded off of. - var origin = $('tr[data-id=' + $(row).data('origin') + ']'); - var td = origin.children('td.filename'); - var oldBackgroundImage = td.css('background-image'); - td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); - $.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: target }, function(result) { - if (result) { - if (result.status === 'success') { - FileList.remove(file); - procesSelection(); - $('#notification').hide(); - } else { - $('#notification').hide(); - $('#notification').text(result.data.message); - $('#notification').fadeIn(); - } - } else { - OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); - } - td.css('background-image', oldBackgroundImage); - }); - }); - }, - tolerance: 'pointer' -}; - function procesSelection() { - var selected = getSelectedFilesTrash(); + var selected = Files.getSelectedFiles(); var selectedFiles = selected.filter(function(el) { return el.type==='file'; }); @@ -711,7 +609,7 @@ function procesSelection() { * if property is set, an array with that property for each file is returnd * if it's ommited an array of objects with all properties is returned */ -function getSelectedFilesTrash(property) { +Files.getSelectedFiles = function(property) { var elements=$('td.filename input:checkbox:checked').parent().parent(); var files=[]; elements.each(function(i,element) { @@ -737,7 +635,7 @@ Files.getMimeIcon = function(mime, ready) { ready(Files.getMimeIcon.cache[mime]); } else { $.get( OC.filePath('files','ajax','mimeicon.php'), {mime: mime}, function(path) { - if(SVGSupport()){ + if(OC.Util.hasSVGSupport()){ path = path.substr(0, path.length-4) + '.svg'; } Files.getMimeIcon.cache[mime]=path; @@ -752,25 +650,32 @@ function getPathForPreview(name) { return path; } +/** + * Generates a preview URL based on the URL space. + * @param urlSpec map with {x: width, y: height, file: file path} + * @return preview URL + */ +Files.generatePreviewUrl = function(urlSpec) { + urlSpec = urlSpec || {}; + if (!urlSpec.x) { + urlSpec.x = $('#filestable').data('preview-x'); + } + if (!urlSpec.y) { + urlSpec.y = $('#filestable').data('preview-y'); + } + urlSpec.y *= window.devicePixelRatio; + urlSpec.x *= window.devicePixelRatio; + urlSpec.forceIcon = 0; + return OC.generateUrl('/core/preview.png?') + $.param(urlSpec); +} + Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { // get mime icon url Files.getMimeIcon(mime, function(iconURL) { - var urlSpec = {}; - var previewURL; + var previewURL, + urlSpec = {}; ready(iconURL); // set mimeicon URL - // now try getting a preview thumbnail URL - if ( ! width ) { - width = $('#filestable').data('preview-x'); - } - if ( ! height ) { - height = $('#filestable').data('preview-y'); - } - // note: the order of arguments must match the one - // from the server's template so that the browser - // knows it's the same file for caching - urlSpec.x = width; - urlSpec.y = height; urlSpec.file = Files.fixPath(path); if (etag){ @@ -781,15 +686,9 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { console.warn('Files.lazyLoadPreview(): missing etag argument'); } - if ( $('#isPublic').length ) { - urlSpec.t = $('#dirToken').val(); - previewURL = OC.generateUrl('/publicpreview.png?') + $.param(urlSpec); - } else { - previewURL = OC.generateUrl('/core/preview.png?') + $.param(urlSpec); - } + previewURL = Files.generatePreviewUrl(urlSpec); previewURL = previewURL.replace('(', '%28'); previewURL = previewURL.replace(')', '%29'); - previewURL += '&forceIcon=0'; // preload image to prevent delay // this will make the browser cache the image @@ -799,7 +698,7 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { if (img.width > 5) { ready(previewURL); } - } + }; img.src = previewURL; }); }; @@ -838,14 +737,8 @@ function checkTrashStatus() { }); } -function onClickBreadcrumb(e) { - var $el = $(e.target).closest('.crumb'), - $targetDir = $el.data('dir'), - isPublic = !!$('#isPublic').val(); - - if ($targetDir !== undefined && !isPublic) { - e.preventDefault(); - FileList.changeDirectory(decodeURIComponent($targetDir)); - } +// override core's fileDownloadPath (legacy) +function fileDownloadPath(dir, file) { + return Files.getDownloadUrl(file, dir); } diff --git a/apps/files/l10n/ar.php b/apps/files/l10n/ar.php index 147d77d4cb08df4c52c22fc68d55b93fe88ac137..e7c081b1c47e1d066cb758ae316bf8507687780e 100644 --- a/apps/files/l10n/ar.php +++ b/apps/files/l10n/ar.php @@ -27,9 +27,9 @@ $TRANSLATIONS = array( "Share" => "شارك", "Delete permanently" => "حذف بشكل دائم", "Rename" => "إعادة تسميه", +"Error moving file" => "حدث خطأ أثناء نقل الملف", +"Error" => "خطأ", "Pending" => "قيد الانتظار", -"replaced {new_name} with {old_name}" => "استبدل {new_name} بـ {old_name}", -"undo" => "تراجع", "_%n folder_::_%n folders_" => array("لا يوجد مجلدات %n","1 مجلد %n","2 مجلد %n","عدد قليل من مجلدات %n","عدد كبير من مجلدات %n","مجلدات %n"), "_%n file_::_%n files_" => array("لا يوجد ملفات %n","ملف %n","2 ملف %n","قليل من ملفات %n","الكثير من ملفات %n"," ملفات %n"), "{dirs} and {files}" => "{dirs} و {files}", @@ -40,8 +40,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "المفتاح الخاص بتشفير التطبيقات غير صالح. يرجى تحديث كلمة السر الخاصة بالمفتاح الخاص من الإعدادت الشخصية حتى تتمكن من الوصول للملفات المشفرة.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "تم تعطيل التشفير لكن ملفاتك لا تزال مشفرة. فضلا اذهب إلى الإعدادات الشخصية لإزالة التشفير عن ملفاتك.", "Your download is being prepared. This might take some time if the files are big." => "جاري تجهيز عملية التحميل. قد تستغرق بعض الوقت اذا كان حجم الملفات كبير.", -"Error moving file" => "حدث خطأ أثناء نقل الملف", -"Error" => "خطأ", "Name" => "اسم", "Size" => "حجم", "Modified" => "معدل", diff --git a/apps/files/l10n/ast.php b/apps/files/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..93ae47b25c563eb039b9f565675d52f8faf0542a --- /dev/null +++ b/apps/files/l10n/ast.php @@ -0,0 +1,29 @@ + "El nome de ficheru nun pue quedar baleru.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome inválidu, los caráuteres \"\\\", \"/\", \"<\", \">\", \":\", \"\", \"|\" \"?\" y \"*\" nun tán permitíos.", +"No file was uploaded. Unknown error" => "Nun se xubió dengún ficheru. Fallu desconocíu", +"There is no error, the file uploaded with success" => "Nun hai dengún fallu, el ficheru xubióse ensin problemes", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "El ficheru xubíu perpasa la direutiva \"MAX_FILE_SIZE\" especificada nel formulariu HTML", +"The uploaded file was only partially uploaded" => "El ficheru xubióse de mou parcial", +"No file was uploaded" => "Nun se xubió dengún ficheru", +"Missing a temporary folder" => "Falta una carpeta temporal", +"Failed to write to disk" => "Fallu al escribir al discu", +"Not enough storage available" => "Nun hai abondu espaciu disponible", +"Files" => "Ficheros", +"Share" => "Compartir", +"Rename" => "Renomar", +"Error" => "Fallu", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), +"Name" => "Nome", +"Size" => "Tamañu", +"Upload" => "Xubir", +"Save" => "Guardar", +"New folder" => "Nueva carpeta", +"Cancel upload" => "Encaboxar xuba", +"Download" => "Descargar", +"Delete" => "Desaniciar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/be.php b/apps/files/l10n/be.php index 830400b93fbf643f6cea6e83b0fb51f0519e0221..f97fc27e2d176fdb941614952e9f705e973b9859 100644 --- a/apps/files/l10n/be.php +++ b/apps/files/l10n/be.php @@ -1,8 +1,8 @@ "Памылка", "_%n folder_::_%n folders_" => array("","","",""), "_%n file_::_%n files_" => array("","","",""), -"_Uploading %n file_::_Uploading %n files_" => array("","","",""), -"Error" => "Памылка" +"_Uploading %n file_::_Uploading %n files_" => array("","","","") ); $PLURAL_FORMS = "nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/files/l10n/bg_BG.php b/apps/files/l10n/bg_BG.php index 12e699064be74512d19947e007a52e320553e042..2418010cdd9a747a4b80074e1ac771cc8e0f455b 100644 --- a/apps/files/l10n/bg_BG.php +++ b/apps/files/l10n/bg_BG.php @@ -12,12 +12,11 @@ $TRANSLATIONS = array( "Share" => "Споделяне", "Delete permanently" => "Изтриване завинаги", "Rename" => "Преименуване", +"Error" => "Грешка", "Pending" => "Чакащо", -"undo" => "възтановяване", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "Грешка", "Name" => "Име", "Size" => "Размер", "Modified" => "Променено", diff --git a/apps/files/l10n/bn_BD.php b/apps/files/l10n/bn_BD.php index 11f3525690b8f5d6409683e6813a2c45ff151668..667a68bb6277fa42f923697741d373666c26b9c9 100644 --- a/apps/files/l10n/bn_BD.php +++ b/apps/files/l10n/bn_BD.php @@ -19,13 +19,11 @@ $TRANSLATIONS = array( "{new_name} already exists" => "{new_name} টি বিদ্যমান", "Share" => "ভাগাভাগি কর", "Rename" => "পূনঃনামকরণ", +"Error" => "সমস্যা", "Pending" => "মুলতুবি", -"replaced {new_name} with {old_name}" => "{new_name} কে {old_name} নামে প্রতিস্থাপন করা হয়েছে", -"undo" => "ক্রিয়া প্রত্যাহার", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "সমস্যা", "Name" => "রাম", "Size" => "আকার", "Modified" => "পরিবর্তিত", diff --git a/apps/files/l10n/ca.php b/apps/files/l10n/ca.php index a4418b1be50fd8a2731ee054a56a4d12398b563d..8ef9b764484519005a77d986580a44cbf710e52b 100644 --- a/apps/files/l10n/ca.php +++ b/apps/files/l10n/ca.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Comparteix", "Delete permanently" => "Esborra permanentment", "Rename" => "Reanomena", +"Error moving file" => "Error en moure el fitxer", +"Error" => "Error", "Pending" => "Pendent", "Could not rename file" => "No es pot canviar el nom de fitxer", -"replaced {new_name} with {old_name}" => "s'ha substituït {old_name} per {new_name}", -"undo" => "desfés", "Error deleting file." => "Error en esborrar el fitxer.", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetes"), "_%n file_::_%n files_" => array("%n fitxer","%n fitxers"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "La clau privada de l'aplicació d'encriptació no és vàlida! Actualitzeu la contrasenya de la clau privada a l'arranjament personal per recuperar els fitxers encriptats.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "L'encriptació s'ha desactivat però els vostres fitxers segueixen encriptats. Aneu a la vostra configuració personal per desencriptar els vostres fitxers.", "Your download is being prepared. This might take some time if the files are big." => "S'està preparant la baixada. Pot trigar una estona si els fitxers són grans.", -"Error moving file" => "Error en moure el fitxer", -"Error" => "Error", "Name" => "Nom", "Size" => "Mida", "Modified" => "Modificat", diff --git a/apps/files/l10n/cs_CZ.php b/apps/files/l10n/cs_CZ.php index 5bcf1087b9c5e38925476b10fed8bdf427d89380..8aea17a7051bc5ba3947db4ad29f809c670d1b3a 100644 --- a/apps/files/l10n/cs_CZ.php +++ b/apps/files/l10n/cs_CZ.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Sdílet", "Delete permanently" => "Trvale odstranit", "Rename" => "Přejmenovat", +"Error moving file" => "Chyba při přesunu souboru", +"Error" => "Chyba", "Pending" => "Nevyřízené", "Could not rename file" => "Nepodařilo se přejmenovat soubor", -"replaced {new_name} with {old_name}" => "nahrazeno {new_name} s {old_name}", -"undo" => "vrátit zpět", "Error deleting file." => "Chyba při mazání souboru.", "_%n folder_::_%n folders_" => array("%n složka","%n složky","%n složek"), "_%n file_::_%n files_" => array("%n soubor","%n soubory","%n souborů"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Chybný soukromý klíč pro šifrovací aplikaci. Aktualizujte prosím heslo svého soukromého klíče ve vašem osobním nastavení, abyste znovu získali přístup k vašim zašifrovaným souborům.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Šifrování bylo vypnuto, vaše soubory jsou však stále zašifrované. Běžte prosím do osobního nastavení, kde soubory odšifrujete.", "Your download is being prepared. This might take some time if the files are big." => "Vaše soubory ke stažení se připravují. Pokud jsou velké, může to chvíli trvat.", -"Error moving file" => "Chyba při přesunu souboru", -"Error" => "Chyba", "Name" => "Název", "Size" => "Velikost", "Modified" => "Upraveno", diff --git a/apps/files/l10n/cy_GB.php b/apps/files/l10n/cy_GB.php index df93ca507b1191c92dfabeabe52a6a11f259c2c9..b27e4c3bfc2a53350eb17118d59fd72ef7200949 100644 --- a/apps/files/l10n/cy_GB.php +++ b/apps/files/l10n/cy_GB.php @@ -21,16 +21,14 @@ $TRANSLATIONS = array( "Share" => "Rhannu", "Delete permanently" => "Dileu'n barhaol", "Rename" => "Ailenwi", +"Error" => "Gwall", "Pending" => "I ddod", -"replaced {new_name} with {old_name}" => "newidiwyd {new_name} yn lle {old_name}", -"undo" => "dadwneud", "_%n folder_::_%n folders_" => array("","","",""), "_%n file_::_%n files_" => array("","","",""), "_Uploading %n file_::_Uploading %n files_" => array("","","",""), "Your storage is full, files can not be updated or synced anymore!" => "Mae eich storfa'n llawn, ni ellir diweddaru a chydweddu ffeiliau mwyach!", "Your storage is almost full ({usedSpacePercent}%)" => "Mae eich storfa bron a bod yn llawn ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Wrthi'n paratoi i lwytho i lawr. Gall gymryd peth amser os yw'r ffeiliau'n fawr.", -"Error" => "Gwall", "Name" => "Enw", "Size" => "Maint", "Modified" => "Addaswyd", diff --git a/apps/files/l10n/da.php b/apps/files/l10n/da.php index 7069849b430305d3edf95f6b5b0d6e14b851f834..6a7ea4745ccbfc8da1f6f13202b0f32a6bbc0355 100644 --- a/apps/files/l10n/da.php +++ b/apps/files/l10n/da.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Del", "Delete permanently" => "Slet permanent", "Rename" => "Omdøb", +"Error moving file" => "Fejl ved flytning af fil", +"Error" => "Fejl", "Pending" => "Afventer", "Could not rename file" => "Kunne ikke omdøbe filen", -"replaced {new_name} with {old_name}" => "erstattede {new_name} med {old_name}", -"undo" => "fortryd", "Error deleting file." => "Fejl ved sletnign af fil.", "_%n folder_::_%n folders_" => array("%n mappe","%n mapper"), "_%n file_::_%n files_" => array("%n fil","%n filer"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Ugyldig privat nøgle for krypteringsprogrammet. Opdater venligst dit kodeord for den private nøgle i dine personlige indstillinger. Det kræves for at få adgang til dine krypterede filer.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Krypteringen blev deaktiveret, men dine filer er stadig krypteret. Gå venligst til dine personlige indstillinger for at dekryptere dine filer. ", "Your download is being prepared. This might take some time if the files are big." => "Dit download forberedes. Dette kan tage lidt tid ved større filer.", -"Error moving file" => "Fejl ved flytning af fil", -"Error" => "Fejl", "Name" => "Navn", "Size" => "Størrelse", "Modified" => "Ændret", diff --git a/apps/files/l10n/de.php b/apps/files/l10n/de.php index 376cbaa4e25146857efb8f1967e54344bf996d85..401ee243f2894af26ed0d30d9417b292f1daf506 100644 --- a/apps/files/l10n/de.php +++ b/apps/files/l10n/de.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Teilen", "Delete permanently" => "Endgültig löschen", "Rename" => "Umbenennen", +"Error moving file" => "Fehler beim Verschieben der Datei", +"Error" => "Fehler", "Pending" => "Ausstehend", "Could not rename file" => "Die Datei konnte nicht umbenannt werden", -"replaced {new_name} with {old_name}" => "{old_name} ersetzt durch {new_name}", -"undo" => "rückgängig machen", "Error deleting file." => "Fehler beim Löschen der Datei.", "_%n folder_::_%n folders_" => array("%n Ordner","%n Ordner"), "_%n file_::_%n files_" => array("%n Datei","%n Dateien"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Ungültiger privater Schlüssel für die Verschlüsselung-App. Bitte aktualisiere Dein privates Schlüssel-Passwort, um den Zugriff auf Deine verschlüsselten Dateien wiederherzustellen.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Die Verschlüsselung wurde deaktiviert, jedoch sind Deine Dateien nach wie vor verschlüsselt. Bitte gehe zu Deinen persönlichen Einstellungen, um Deine Dateien zu entschlüsseln.", "Your download is being prepared. This might take some time if the files are big." => "Dein Download wird vorbereitet. Dies kann bei größeren Dateien etwas dauern.", -"Error moving file" => "Fehler beim Verschieben der Datei", -"Error" => "Fehler", "Name" => "Name", "Size" => "Größe", "Modified" => "Geändert", diff --git a/apps/files/l10n/de_CH.php b/apps/files/l10n/de_CH.php index 8b70d7f0f062442093473565f029ceb6d13f9824..f797be99e9829d20e1f19c6f381b3319d0324f7f 100644 --- a/apps/files/l10n/de_CH.php +++ b/apps/files/l10n/de_CH.php @@ -23,9 +23,8 @@ $TRANSLATIONS = array( "Share" => "Teilen", "Delete permanently" => "Endgültig löschen", "Rename" => "Umbenennen", +"Error" => "Fehler", "Pending" => "Ausstehend", -"replaced {new_name} with {old_name}" => "{old_name} wurde ersetzt durch {new_name}", -"undo" => "rückgängig machen", "_%n folder_::_%n folders_" => array("","%n Ordner"), "_%n file_::_%n files_" => array("","%n Dateien"), "_Uploading %n file_::_Uploading %n files_" => array("%n Datei wird hochgeladen","%n Dateien werden hochgeladen"), @@ -33,7 +32,6 @@ $TRANSLATIONS = array( "Your storage is almost full ({usedSpacePercent}%)" => "Ihr Speicher ist fast voll ({usedSpacePercent}%)", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Die Verschlüsselung wurde deaktiviert, jedoch sind Ihre Dateien nach wie vor verschlüsselt. Bitte gehen Sie zu Ihren persönlichen Einstellungen, um Ihre Dateien zu entschlüsseln.", "Your download is being prepared. This might take some time if the files are big." => "Ihr Download wird vorbereitet. Dies kann bei grösseren Dateien etwas dauern.", -"Error" => "Fehler", "Name" => "Name", "Size" => "Grösse", "Modified" => "Geändert", diff --git a/apps/files/l10n/de_DE.php b/apps/files/l10n/de_DE.php index 0df0f46dc24ff4179a1019621ed8f32cfa630b1a..4768faa97da79daf1c117d6dcd0d1342ad06aa4b 100644 --- a/apps/files/l10n/de_DE.php +++ b/apps/files/l10n/de_DE.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Teilen", "Delete permanently" => "Endgültig löschen", "Rename" => "Umbenennen", +"Error moving file" => "Fehler beim Verschieben der Datei", +"Error" => "Fehler", "Pending" => "Ausstehend", "Could not rename file" => "Die Datei konnte nicht umbenannt werden", -"replaced {new_name} with {old_name}" => "{old_name} wurde ersetzt durch {new_name}", -"undo" => "rückgängig machen", "Error deleting file." => "Fehler beim Löschen der Datei.", "_%n folder_::_%n folders_" => array("%n Ordner","%n Ordner"), "_%n file_::_%n files_" => array("%n Datei","%n Dateien"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Ungültiger privater Schlüssel für die Verschlüsselung-App. Bitte aktualisieren Sie Ihr privates Schlüssel-Passwort, um den Zugriff auf Ihre verschlüsselten Dateien wiederherzustellen.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Die Verschlüsselung wurde deaktiviert, jedoch sind Ihre Dateien nach wie vor verschlüsselt. Bitte gehen Sie zu Ihren persönlichen Einstellungen, um Ihre Dateien zu entschlüsseln.", "Your download is being prepared. This might take some time if the files are big." => "Ihr Download wird vorbereitet. Dies kann bei größeren Dateien etwas dauern.", -"Error moving file" => "Fehler beim Verschieben der Datei", -"Error" => "Fehler", "Name" => "Name", "Size" => "Größe", "Modified" => "Geändert", diff --git a/apps/files/l10n/el.php b/apps/files/l10n/el.php index 9144cf3ea10c9713c0bbeaab040871182376e70d..713072d3e0e24890ac870f4c66dce7becdcc84e3 100644 --- a/apps/files/l10n/el.php +++ b/apps/files/l10n/el.php @@ -5,6 +5,7 @@ $TRANSLATIONS = array( "File name cannot be empty." => "Το όνομα αρχείου δεν μπορεί να είναι κενό.", "\"%s\" is an invalid file name." => "Το \"%s\" είναι ένα μη έγκυρο όνομα αρχείου.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Μη έγκυρο όνομα, '\\', '/', '<', '>', ':', '\"', '|', '?' και '*' δεν επιτρέπονται.", +"The target folder has been moved or deleted." => "Ο φάκελος προορισμού έχει μετακινηθεί ή διαγραφεί.", "The name %s is already used in the folder %s. Please choose a different name." => "Το όνομα %s χρησιμοποιείτε ήδη στον φάκελο %s. Παρακαλώ επιλέξτε ένα άλλο όνομα.", "Not a valid source" => "Μη έγκυρη πηγή", "Server is not allowed to open URLs, please check the server configuration" => "Ο διακομιστής δεν επιτρέπεται να ανοίγει URL, παρακαλώ ελέγξτε τις ρυθμίσεις του διακομιστή", @@ -28,6 +29,8 @@ $TRANSLATIONS = array( "Invalid directory." => "Μη έγκυρος φάκελος.", "Files" => "Αρχεία", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Αδυναμία φόρτωσης {filename} καθώς είναι κατάλογος αρχείων ή έχει 0 bytes", +"Total file size {size1} exceeds upload limit {size2}" => "Το συνολικό μέγεθος αρχείου {size1} υπερβαίνει το όριο μεταφόρτωσης {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Δεν υπάρχει αρκετός ελεύθερος χώρος, μεταφορτώνετε μέγεθος {size1} αλλά υπάρχει χώρος μόνο {size2}", "Upload cancelled." => "Η αποστολή ακυρώθηκε.", "Could not get result from server." => "Αδυναμία λήψης αποτελέσματος από το διακομιστή.", "File upload is in progress. Leaving the page now will cancel the upload." => "Η αποστολή του αρχείου βρίσκεται σε εξέλιξη. Το κλείσιμο της σελίδας θα ακυρώσει την αποστολή.", @@ -40,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Διαμοιρασμός", "Delete permanently" => "Μόνιμη διαγραφή", "Rename" => "Μετονομασία", +"Error moving file" => "Σφάλμα κατά τη μετακίνηση του αρχείου", +"Error" => "Σφάλμα", "Pending" => "Εκκρεμεί", "Could not rename file" => "Αδυναμία μετονομασίας αρχείου", -"replaced {new_name} with {old_name}" => "αντικαταστάθηκε το {new_name} με {old_name}", -"undo" => "αναίρεση", "Error deleting file." => "Σφάλμα διαγραφής αρχείου.", "_%n folder_::_%n folders_" => array("%n φάκελος","%n φάκελοι"), "_%n file_::_%n files_" => array("%n αρχείο","%n αρχεία"), @@ -56,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Άκυρο προσωπικό κλειδί για την εφαρμογή κρυπτογράφησης. Παρακαλώ ενημερώστε τον κωδικό του προσωπικού κλειδίου σας στις προσωπικές ρυθμίσεις για να επανακτήσετε πρόσβαση στα κρυπτογραφημένα σας αρχεία.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Η κρυπτογράφηση απενεργοποιήθηκε, αλλά τα αρχεία σας είναι ακόμα κρυπτογραφημένα. Παρακαλούμε απενεργοποιήσετε την κρυπτογράφηση αρχείων από τις προσωπικές σας ρυθμίσεις", "Your download is being prepared. This might take some time if the files are big." => "Η λήψη προετοιμάζεται. Αυτό μπορεί να πάρει ώρα εάν τα αρχεία έχουν μεγάλο μέγεθος.", -"Error moving file" => "Σφάλμα κατά τη μετακίνηση του αρχείου", -"Error" => "Σφάλμα", "Name" => "Όνομα", "Size" => "Μέγεθος", "Modified" => "Τροποποιήθηκε", diff --git a/apps/files/l10n/en_GB.php b/apps/files/l10n/en_GB.php index 3fb2cb62e609cf9572f92c1e122783266fd456d1..705f6b99b0b25f84357d567fbd1520b45ae33c4b 100644 --- a/apps/files/l10n/en_GB.php +++ b/apps/files/l10n/en_GB.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Share", "Delete permanently" => "Delete permanently", "Rename" => "Rename", +"Error moving file" => "Error moving file", +"Error" => "Error", "Pending" => "Pending", "Could not rename file" => "Could not rename file", -"replaced {new_name} with {old_name}" => "replaced {new_name} with {old_name}", -"undo" => "undo", "Error deleting file." => "Error deleting file.", "_%n folder_::_%n folders_" => array("%n folder","%n folders"), "_%n file_::_%n files_" => array("%n file","%n files"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.", "Your download is being prepared. This might take some time if the files are big." => "Your download is being prepared. This might take some time if the files are big.", -"Error moving file" => "Error moving file", -"Error" => "Error", "Name" => "Name", "Size" => "Size", "Modified" => "Modified", diff --git a/apps/files/l10n/eo.php b/apps/files/l10n/eo.php index b92fef50006a1a36c9cb2c5d2aa6e843063c173b..a6e0d553177e66387a183a373a75bd655297cb46 100644 --- a/apps/files/l10n/eo.php +++ b/apps/files/l10n/eo.php @@ -35,10 +35,10 @@ $TRANSLATIONS = array( "Share" => "Kunhavigi", "Delete permanently" => "Forigi por ĉiam", "Rename" => "Alinomigi", +"Error moving file" => "Eraris movo de dosiero", +"Error" => "Eraro", "Pending" => "Traktotaj", "Could not rename file" => "Ne povis alinomiĝi dosiero", -"replaced {new_name} with {old_name}" => "anstataŭiĝis {new_name} per {old_name}", -"undo" => "malfari", "_%n folder_::_%n folders_" => array("%n dosierujo","%n dosierujoj"), "_%n file_::_%n files_" => array("%n dosiero","%n dosieroj"), "{dirs} and {files}" => "{dirs} kaj {files}", @@ -46,8 +46,6 @@ $TRANSLATIONS = array( "Your storage is full, files can not be updated or synced anymore!" => "Via memoro plenas, ne plu eblas ĝisdatigi aŭ sinkronigi dosierojn!", "Your storage is almost full ({usedSpacePercent}%)" => "Via memoro preskaŭ plenas ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Via elŝuto pretiĝatas. Ĉi tio povas daŭri iom da tempo se la dosieroj grandas.", -"Error moving file" => "Eraris movo de dosiero", -"Error" => "Eraro", "Name" => "Nomo", "Size" => "Grando", "Modified" => "Modifita", diff --git a/apps/files/l10n/es.php b/apps/files/l10n/es.php index 6083ab2a5d68b24e1eb6a1a2c8ba6a539add19a6..10a378c371bd1cf7bd0f9542421b9908252032c1 100644 --- a/apps/files/l10n/es.php +++ b/apps/files/l10n/es.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renombrar", +"Error moving file" => "Error moviendo archivo", +"Error" => "Error", "Pending" => "Pendiente", "Could not rename file" => "No se pudo renombrar el archivo", -"replaced {new_name} with {old_name}" => "reemplazado {new_name} con {old_name}", -"undo" => "deshacer", "Error deleting file." => "Error al borrar el archivo", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), "_%n file_::_%n files_" => array("%n archivo","%n archivos"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "La clave privada no es válida para la app de cifrado. Por favor, actualiza la contraseña de tu clave privada en tus ajustes personales para recuperar el acceso a tus archivos cifrados.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "El cifrado ha sido deshabilitado pero tus archivos permanecen cifrados. Por favor, ve a tus ajustes personales para descifrar tus archivos.", "Your download is being prepared. This might take some time if the files are big." => "Su descarga está siendo preparada. Esto podría tardar algo de tiempo si los archivos son grandes.", -"Error moving file" => "Error moviendo archivo", -"Error" => "Error", "Name" => "Nombre", "Size" => "Tamaño", "Modified" => "Modificado", diff --git a/apps/files/l10n/es_AR.php b/apps/files/l10n/es_AR.php index 105321276c1b1ea370ebedd2e783678f1bd05c2d..f78615fc923d438a9a241ebf05d0b0e66f425390 100644 --- a/apps/files/l10n/es_AR.php +++ b/apps/files/l10n/es_AR.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Borrar permanentemente", "Rename" => "Cambiar nombre", +"Error moving file" => "Error moviendo el archivo", +"Error" => "Error", "Pending" => "Pendientes", "Could not rename file" => "No se pudo renombrar el archivo", -"replaced {new_name} with {old_name}" => "se reemplazó {new_name} con {old_name}", -"undo" => "deshacer", "Error deleting file." => "Error al borrar el archivo.", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), "_%n file_::_%n files_" => array("%n archivo","%n archivos"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Llave privada inválida para la aplicación de encriptación. Por favor actualice la clave de la llave privada en las configuraciones personales para recobrar el acceso a sus archivos encriptados.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "El proceso de cifrado se ha desactivado, pero los archivos aún están encriptados. Por favor, vaya a la configuración personal para descifrar los archivos.", "Your download is being prepared. This might take some time if the files are big." => "Tu descarga se está preparando. Esto puede demorar si los archivos son muy grandes.", -"Error moving file" => "Error moviendo el archivo", -"Error" => "Error", "Name" => "Nombre", "Size" => "Tamaño", "Modified" => "Modificado", diff --git a/apps/files/l10n/es_CL.php b/apps/files/l10n/es_CL.php index 4f5e35bd887a563157a14b065a526e55a65e15af..8e051d1c389cbeadbe1c689678ab5a86dad73845 100644 --- a/apps/files/l10n/es_CL.php +++ b/apps/files/l10n/es_CL.php @@ -2,10 +2,10 @@ $TRANSLATIONS = array( "Files" => "Archivos", "Share" => "Compartir", +"Error" => "Error", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "Error", "Upload" => "Subir", "Download" => "Descargar" ); diff --git a/apps/files/l10n/es_MX.php b/apps/files/l10n/es_MX.php index f8a72f95d859b2415168a6802731d41bc2ae4ca6..ea7db0d7b9ce1583a634991cadb2aa2e6466b3bf 100644 --- a/apps/files/l10n/es_MX.php +++ b/apps/files/l10n/es_MX.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renombrar", +"Error moving file" => "Error moviendo archivo", +"Error" => "Error", "Pending" => "Pendiente", "Could not rename file" => "No se pudo renombrar el archivo", -"replaced {new_name} with {old_name}" => "reemplazado {new_name} con {old_name}", -"undo" => "deshacer", "Error deleting file." => "Error borrando el archivo.", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), "_%n file_::_%n files_" => array("%n archivo","%n archivos"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "La clave privada no es válida para la aplicación de cifrado. Por favor, actualiza la contraseña de tu clave privada en tus ajustes personales para recuperar el acceso a tus archivos cifrados.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "El cifrado ha sido deshabilitado pero tus archivos permanecen cifrados. Por favor, ve a tus ajustes personales para descifrar tus archivos.", "Your download is being prepared. This might take some time if the files are big." => "Su descarga está siendo preparada. Esto podría tardar algo de tiempo si los archivos son grandes.", -"Error moving file" => "Error moviendo archivo", -"Error" => "Error", "Name" => "Nombre", "Size" => "Tamaño", "Modified" => "Modificado", diff --git a/apps/files/l10n/et_EE.php b/apps/files/l10n/et_EE.php index f1fdc82673c425681d6ece6f24b42b72ea3da6a5..4f0614feb5e9436210abcbbfe6f6b7f64e05296a 100644 --- a/apps/files/l10n/et_EE.php +++ b/apps/files/l10n/et_EE.php @@ -3,7 +3,9 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Ei saa liigutada faili %s - samanimeline fail on juba olemas", "Could not move %s" => "%s liigutamine ebaõnnestus", "File name cannot be empty." => "Faili nimi ei saa olla tühi.", +"\"%s\" is an invalid file name." => "\"%s\" on vigane failinimi.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Vigane nimi, '\\', '/', '<', '>', ':', '\"', '|', '?' ja '*' pole lubatud.", +"The target folder has been moved or deleted." => "Sihtkataloog on ümber tõstetud või kustutatud.", "The name %s is already used in the folder %s. Please choose a different name." => "Nimi %s on juba kasutusel kataloogis %s. Palun vali mõni teine nimi.", "Not a valid source" => "Pole korrektne lähteallikas", "Server is not allowed to open URLs, please check the server configuration" => "Server ei võimalda URL-ide avamist, palun kontrolli serveri seadistust", @@ -27,6 +29,8 @@ $TRANSLATIONS = array( "Invalid directory." => "Vigane kaust.", "Files" => "Failid", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Ei saa üles laadida {filename}, kuna see on kataloog või selle suurus on 0 baiti", +"Total file size {size1} exceeds upload limit {size2}" => "Faili suurus {size1} ületab faili üleslaadimise mahu piirangu {size2}.", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Pole piisavalt vaba ruumi. Sa laadid üles {size1}, kuid ainult {size2} on saadaval.", "Upload cancelled." => "Üleslaadimine tühistati.", "Could not get result from server." => "Serverist ei saadud tulemusi", "File upload is in progress. Leaving the page now will cancel the upload." => "Faili üleslaadimine on töös. Lehelt lahkumine katkestab selle üleslaadimise.", @@ -39,23 +43,22 @@ $TRANSLATIONS = array( "Share" => "Jaga", "Delete permanently" => "Kustuta jäädavalt", "Rename" => "Nimeta ümber", +"Error moving file" => "Viga faili eemaldamisel", +"Error" => "Viga", "Pending" => "Ootel", "Could not rename file" => "Ei suuda faili ümber nimetada", -"replaced {new_name} with {old_name}" => "asendas nime {old_name} nimega {new_name}", -"undo" => "tagasi", "Error deleting file." => "Viga faili kustutamisel.", "_%n folder_::_%n folders_" => array("%n kataloog","%n kataloogi"), "_%n file_::_%n files_" => array("%n fail","%n faili"), "{dirs} and {files}" => "{dirs} ja {files}", "_Uploading %n file_::_Uploading %n files_" => array("Laadin üles %n faili","Laadin üles %n faili"), +"\"{name}\" is an invalid file name." => "\"{name}\" on vigane failinimi.", "Your storage is full, files can not be updated or synced anymore!" => "Sinu andmemaht on täis! Faile ei uuendata ega sünkroniseerita!", "Your storage is almost full ({usedSpacePercent}%)" => "Su andmemaht on peaaegu täis ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Krüpteerimisrakend on lubatud, kuid võtmeid pole lähtestatud. Palun logi välja ning uuesti sisse.", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Vigane Krüpteerimisrakendi privaatvõti . Palun uuenda oma privaatse võtme parool oma personaasete seadete all taastamaks ligipääsu oma krüpteeritud failidele.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Krüpteering on keelatud, kuid sinu failid on endiselt krüpteeritud. Palun vaata oma personaalseid seadeid oma failide dekrüpteerimiseks.", "Your download is being prepared. This might take some time if the files are big." => "Valmistatakse allalaadimist. See võib võtta veidi aega, kui on tegu suurte failidega. ", -"Error moving file" => "Viga faili eemaldamisel", -"Error" => "Viga", "Name" => "Nimi", "Size" => "Suurus", "Modified" => "Muudetud", diff --git a/apps/files/l10n/eu.php b/apps/files/l10n/eu.php index be601eecfbf256e0f89479a350fd1c7262bb1972..d59dd396283ae737cde1de56ea61087c2ab80fdf 100644 --- a/apps/files/l10n/eu.php +++ b/apps/files/l10n/eu.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Elkarbanatu", "Delete permanently" => "Ezabatu betirako", "Rename" => "Berrizendatu", +"Error moving file" => "Errorea fitxategia mugitzean", +"Error" => "Errorea", "Pending" => "Zain", "Could not rename file" => "Ezin izan da fitxategia berrizendatu", -"replaced {new_name} with {old_name}" => " {new_name}-k {old_name} ordezkatu du", -"undo" => "desegin", "Error deleting file." => "Errorea fitxategia ezabatzerakoan.", "_%n folder_::_%n folders_" => array("karpeta %n","%n karpeta"), "_%n file_::_%n files_" => array("fitxategi %n","%n fitxategi"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Enkriptazio aplikaziorako gako pribatu okerra. Mesedez eguneratu zure gako pribatuaren pasahitza zure ezarpen pertsonaletan zure enkriptatuko fitxategietarako sarrera berreskuratzeko.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Enkriptazioa desgaitua izan da baina zure fitxategiak oraindik enkriptatuta daude. Mesedez jo zure ezarpen pertsonaletara zure fitxategiak dekodifikatzeko.", "Your download is being prepared. This might take some time if the files are big." => "Zure deskarga prestatu egin behar da. Denbora bat har lezake fitxategiak handiak badira. ", -"Error moving file" => "Errorea fitxategia mugitzean", -"Error" => "Errorea", "Name" => "Izena", "Size" => "Tamaina", "Modified" => "Aldatuta", diff --git a/apps/files/l10n/fa.php b/apps/files/l10n/fa.php index e1142aba160f5a55db13e4c83e6178e695769556..2e8f6255e2440887a51ab5657c104975aa6e949a 100644 --- a/apps/files/l10n/fa.php +++ b/apps/files/l10n/fa.php @@ -23,16 +23,14 @@ $TRANSLATIONS = array( "Share" => "اشتراک‌گذاری", "Delete permanently" => "حذف قطعی", "Rename" => "تغییرنام", +"Error" => "خطا", "Pending" => "در انتظار", -"replaced {new_name} with {old_name}" => "{نام_جدید} با { نام_قدیمی} جایگزین شد.", -"undo" => "بازگشت", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array("در حال بارگذاری %n فایل"), "Your storage is full, files can not be updated or synced anymore!" => "فضای ذخیره ی شما کاملا پر است، بیش از این فایلها بهنگام یا همگام سازی نمی توانند بشوند!", "Your storage is almost full ({usedSpacePercent}%)" => "فضای ذخیره ی شما تقریبا پر است ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "دانلود شما در حال آماده شدن است. در صورتیکه پرونده ها بزرگ باشند ممکن است مدتی طول بکشد.", -"Error" => "خطا", "Name" => "نام", "Size" => "اندازه", "Modified" => "تاریخ", diff --git a/apps/files/l10n/fi_FI.php b/apps/files/l10n/fi_FI.php index 6b94d8b4fae14f2d4324806ccb4ddefa7a9a8398..b6383c144deab46a501b4b04c4cd93f0ac931a84 100644 --- a/apps/files/l10n/fi_FI.php +++ b/apps/files/l10n/fi_FI.php @@ -41,9 +41,10 @@ $TRANSLATIONS = array( "Share" => "Jaa", "Delete permanently" => "Poista pysyvästi", "Rename" => "Nimeä uudelleen", +"Error moving file" => "Virhe tiedostoa siirrettäessä", +"Error" => "Virhe", "Pending" => "Odottaa", "Could not rename file" => "Tiedoston nimeäminen uudelleen epäonnistui", -"undo" => "kumoa", "Error deleting file." => "Virhe tiedostoa poistaessa.", "_%n folder_::_%n folders_" => array("%n kansio","%n kansiota"), "_%n file_::_%n files_" => array("%n tiedosto","%n tiedostoa"), @@ -54,8 +55,6 @@ $TRANSLATIONS = array( "Your storage is almost full ({usedSpacePercent}%)" => "Tallennustila on melkein loppu ({usedSpacePercent}%)", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Salaus poistettiin käytöstä, mutta tiedostosi ovat edelleen salattuina. Siirry henkilökohtaisiin asetuksiin avataksesi tiedostojesi salauksen.", "Your download is being prepared. This might take some time if the files are big." => "Lataustasi valmistellaan. Tämä saattaa kestää hetken, jos tiedostot ovat suuria kooltaan.", -"Error moving file" => "Virhe tiedostoa siirrettäessä", -"Error" => "Virhe", "Name" => "Nimi", "Size" => "Koko", "Modified" => "Muokattu", diff --git a/apps/files/l10n/fr.php b/apps/files/l10n/fr.php index ad768f03de72c7b9d4793d65783e04a8200f152f..0eed6a70f91d9d4d0c6cb1cec8de6565b33ff3e7 100644 --- a/apps/files/l10n/fr.php +++ b/apps/files/l10n/fr.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Partager", "Delete permanently" => "Supprimer de façon définitive", "Rename" => "Renommer", +"Error moving file" => "Erreur lors du déplacement du fichier", +"Error" => "Erreur", "Pending" => "En attente", "Could not rename file" => "Impossible de renommer le fichier", -"replaced {new_name} with {old_name}" => "{new_name} a été remplacé par {old_name}", -"undo" => "annuler", "Error deleting file." => "Erreur pendant la suppression du fichier.", "_%n folder_::_%n folders_" => array("%n dossier","%n dossiers"), "_%n file_::_%n files_" => array("%n fichier","%n fichiers"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Votre clef privée pour l'application de chiffrement est invalide ! Veuillez mettre à jour le mot de passe de votre clef privée dans vos paramètres personnels pour récupérer l'accès à vos fichiers chiffrés.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Le chiffrement était désactivé mais vos fichiers sont toujours chiffrés. Veuillez vous rendre sur vos Paramètres personnels pour déchiffrer vos fichiers.", "Your download is being prepared. This might take some time if the files are big." => "Votre téléchargement est cours de préparation. Ceci peut nécessiter un certain temps si les fichiers sont volumineux.", -"Error moving file" => "Erreur lors du déplacement du fichier", -"Error" => "Erreur", "Name" => "Nom", "Size" => "Taille", "Modified" => "Modifié", diff --git a/apps/files/l10n/gl.php b/apps/files/l10n/gl.php index 7ea8181dc713412707b4ba3b46fa938af2dd7ced..9fe6546de510a1663bf76e2ab8676c0d02a1895a 100644 --- a/apps/files/l10n/gl.php +++ b/apps/files/l10n/gl.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renomear", +"Error moving file" => "Produciuse un erro ao mover o ficheiro", +"Error" => "Erro", "Pending" => "Pendentes", "Could not rename file" => "Non foi posíbel renomear o ficheiro", -"replaced {new_name} with {old_name}" => "substituír {new_name} por {old_name}", -"undo" => "desfacer", "Error deleting file." => "Produciuse un erro ao eliminar o ficheiro.", "_%n folder_::_%n folders_" => array("%n cartafol","%n cartafoles"), "_%n file_::_%n files_" => array("%n ficheiro","%n ficheiros"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "A chave privada para o aplicativo de cifrado non é correcta. Actualice o contrasinal da súa chave privada nos seus axustes persoais para recuperar o acceso aos seus ficheiros cifrados.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "O cifrado foi desactivado, mais os ficheiros están cifrados. Vaia á configuración persoal para descifrar os ficheiros.", "Your download is being prepared. This might take some time if the files are big." => "Está a prepararse a súa descarga. Isto pode levar bastante tempo se os ficheiros son grandes.", -"Error moving file" => "Produciuse un erro ao mover o ficheiro", -"Error" => "Erro", "Name" => "Nome", "Size" => "Tamaño", "Modified" => "Modificado", diff --git a/apps/files/l10n/he.php b/apps/files/l10n/he.php index 2035c8488bd284e638e0a5b7e3fe895e6692270e..ab8640a91d14e805e7f01dbad6ffb0bfd077acd8 100644 --- a/apps/files/l10n/he.php +++ b/apps/files/l10n/he.php @@ -23,14 +23,12 @@ $TRANSLATIONS = array( "Share" => "שתף", "Delete permanently" => "מחק לצמיתות", "Rename" => "שינוי שם", +"Error" => "שגיאה", "Pending" => "ממתין", -"replaced {new_name} with {old_name}" => "{new_name} הוחלף ב־{old_name}", -"undo" => "ביטול", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), "Your storage is almost full ({usedSpacePercent}%)" => "שטח האחסון שלך כמעט מלא ({usedSpacePercent}%)", -"Error" => "שגיאה", "Name" => "שם", "Size" => "גודל", "Modified" => "זמן שינוי", diff --git a/apps/files/l10n/hi.php b/apps/files/l10n/hi.php index ae01bfc47e1ac6f2fb3043a291f650d4d6124c29..b4234b513765f6fbc79e0da6528efb848d09b1dd 100644 --- a/apps/files/l10n/hi.php +++ b/apps/files/l10n/hi.php @@ -1,10 +1,10 @@ "साझा करें", +"Error" => "त्रुटि", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "त्रुटि", "Upload" => "अपलोड ", "Save" => "सहेजें" ); diff --git a/apps/files/l10n/hr.php b/apps/files/l10n/hr.php index 5048a15c8bbe0c2fb0612ce8a6410dcafb768ca9..ef978e6cfb71d74962cb16a6382e6d6a83b1c701 100644 --- a/apps/files/l10n/hr.php +++ b/apps/files/l10n/hr.php @@ -11,12 +11,11 @@ $TRANSLATIONS = array( "File upload is in progress. Leaving the page now will cancel the upload." => "Učitavanje datoteke. Napuštanjem stranice će prekinuti učitavanje.", "Share" => "Podijeli", "Rename" => "Promjeni ime", +"Error" => "Greška", "Pending" => "U tijeku", -"undo" => "vrati", "_%n folder_::_%n folders_" => array("","",""), "_%n file_::_%n files_" => array("","",""), "_Uploading %n file_::_Uploading %n files_" => array("","",""), -"Error" => "Greška", "Name" => "Ime", "Size" => "Veličina", "Modified" => "Zadnja promjena", diff --git a/apps/files/l10n/hu_HU.php b/apps/files/l10n/hu_HU.php index 6f5ba9b472498ebfdd15333f7ec48631a114d667..e4ab355c9b1fe4c57261e2c0f98b03f4d2ba6f2d 100644 --- a/apps/files/l10n/hu_HU.php +++ b/apps/files/l10n/hu_HU.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Megosztás", "Delete permanently" => "Végleges törlés", "Rename" => "Átnevezés", +"Error moving file" => "Az állomány áthelyezése nem sikerült.", +"Error" => "Hiba", "Pending" => "Folyamatban", "Could not rename file" => "Az állomány nem nevezhető át", -"replaced {new_name} with {old_name}" => "{new_name} fájlt kicseréltük ezzel: {old_name}", -"undo" => "visszavonás", "Error deleting file." => "Hiba a file törlése közben.", "_%n folder_::_%n folders_" => array("%n mappa","%n mappa"), "_%n file_::_%n files_" => array("%n állomány","%n állomány"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Az állományok titkosításához használt titkos kulcsa érvénytelen. Kérjük frissítse a titkos kulcs jelszót a személyes beállításokban, hogy ismét hozzáférjen a titkosított állományaihoz!", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "A titkosítási funkciót kikapcsolták, de az Ön állományai még mindig titkosított állapotban vannak. A személyes beállításoknál tudja a titkosítást feloldani.", "Your download is being prepared. This might take some time if the files are big." => "Készül a letöltendő állomány. Ez eltarthat egy ideig, ha nagyok a fájlok.", -"Error moving file" => "Az állomány áthelyezése nem sikerült.", -"Error" => "Hiba", "Name" => "Név", "Size" => "Méret", "Modified" => "Módosítva", diff --git a/apps/files/l10n/ia.php b/apps/files/l10n/ia.php index 82fd2e658d717bf62e2b0dc8f8350caaefbf1cdb..420e48395c75451ea246e3c660093846ea910000 100644 --- a/apps/files/l10n/ia.php +++ b/apps/files/l10n/ia.php @@ -5,10 +5,10 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Manca un dossier temporari", "Files" => "Files", "Share" => "Compartir", +"Error" => "Error", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "Error", "Name" => "Nomine", "Size" => "Dimension", "Modified" => "Modificate", diff --git a/apps/files/l10n/id.php b/apps/files/l10n/id.php index 45bc05c9182cdd93de9ac4535bd2833140e07133..8356c5465eb377ac08cc5d64f005b649aa0820b9 100644 --- a/apps/files/l10n/id.php +++ b/apps/files/l10n/id.php @@ -37,10 +37,10 @@ $TRANSLATIONS = array( "Share" => "Bagikan", "Delete permanently" => "Hapus secara permanen", "Rename" => "Ubah nama", +"Error moving file" => "Galat saat memindahkan berkas", +"Error" => "Galat", "Pending" => "Menunggu", "Could not rename file" => "Tidak dapat mengubah nama berkas", -"replaced {new_name} with {old_name}" => "mengganti {new_name} dengan {old_name}", -"undo" => "urungkan", "Error deleting file." => "Galat saat menghapus berkas.", "_%n folder_::_%n folders_" => array("%n folder"), "_%n file_::_%n files_" => array("%n berkas"), @@ -52,8 +52,6 @@ $TRANSLATIONS = array( "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 was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Enskripi telah dinonaktifkan tetapi berkas anda tetap dienskripsi. Silakan menuju ke pengaturan pribadi untuk deskrip berkas anda.", "Your download is being prepared. This might take some time if the files are big." => "Unduhan Anda sedang disiapkan. Prosesnya dapat berlangsung agak lama jika ukuran berkasnya besar.", -"Error moving file" => "Galat saat memindahkan berkas", -"Error" => "Galat", "Name" => "Nama", "Size" => "Ukuran", "Modified" => "Dimodifikasi", diff --git a/apps/files/l10n/is.php b/apps/files/l10n/is.php index 088cdefa3048aaf7b5c8e7cf1e922f8c83e6cf1b..00503028e0e7ebbe3edb82279050ea7c7b9af92f 100644 --- a/apps/files/l10n/is.php +++ b/apps/files/l10n/is.php @@ -19,13 +19,11 @@ $TRANSLATIONS = array( "{new_name} already exists" => "{new_name} er þegar til", "Share" => "Deila", "Rename" => "Endurskýra", +"Error" => "Villa", "Pending" => "Bíður", -"replaced {new_name} with {old_name}" => "yfirskrifaði {new_name} með {old_name}", -"undo" => "afturkalla", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "Villa", "Name" => "Nafn", "Size" => "Stærð", "Modified" => "Breytt", diff --git a/apps/files/l10n/it.php b/apps/files/l10n/it.php index e1a34e646fb280f30e7724caf0f4e99c45a3ee7c..9539496a3fc31a0a9674e55cd841754824192178 100644 --- a/apps/files/l10n/it.php +++ b/apps/files/l10n/it.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Condividi", "Delete permanently" => "Elimina definitivamente", "Rename" => "Rinomina", +"Error moving file" => "Errore durante lo spostamento del file", +"Error" => "Errore", "Pending" => "In corso", "Could not rename file" => "Impossibile rinominare il file", -"replaced {new_name} with {old_name}" => "sostituito {new_name} con {old_name}", -"undo" => "annulla", "Error deleting file." => "Errore durante l'eliminazione del file.", "_%n folder_::_%n folders_" => array("%n cartella","%n cartelle"), "_%n file_::_%n files_" => array("%n file","%n file"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Chiave privata non valida per l'applicazione di cifratura. Aggiorna la password della chiave privata nelle impostazioni personali per ripristinare l'accesso ai tuoi file cifrati.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "La cifratura è stata disabilitata ma i tuoi file sono ancora cifrati. Vai nelle impostazioni personali per decifrare i file.", "Your download is being prepared. This might take some time if the files are big." => "Il tuo scaricamento è in fase di preparazione. Ciò potrebbe richiedere del tempo se i file sono grandi.", -"Error moving file" => "Errore durante lo spostamento del file", -"Error" => "Errore", "Name" => "Nome", "Size" => "Dimensione", "Modified" => "Modificato", diff --git a/apps/files/l10n/ja.php b/apps/files/l10n/ja.php index eb6cb0efc505d0f1db43634e9427cd1bc489ccb8..dd8d4e4e3f63f8daf79b715aff7fa297b26d59ac 100644 --- a/apps/files/l10n/ja.php +++ b/apps/files/l10n/ja.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "共有", "Delete permanently" => "完全に削除する", "Rename" => "名前の変更", +"Error moving file" => "ファイルの移動エラー", +"Error" => "エラー", "Pending" => "中断", "Could not rename file" => "ファイルの名前変更ができませんでした", -"replaced {new_name} with {old_name}" => "{old_name} を {new_name} に置換", -"undo" => "元に戻す", "Error deleting file." => "ファイルの削除エラー。", "_%n folder_::_%n folders_" => array("%n 個のフォルダー"), "_%n file_::_%n files_" => array("%n 個のファイル"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "暗号化アプリの無効なプライベートキーです。あなたの暗号化されたファイルへアクセスするために、個人設定からプライベートキーのパスワードを更新してください。", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "暗号化の機能は無効化されましたが、ファイルはすでに暗号化されています。個人設定からファイルを複合を行ってください。", "Your download is being prepared. This might take some time if the files are big." => "ダウンロードの準備中です。ファイルサイズが大きい場合は少し時間がかかるかもしれません。", -"Error moving file" => "ファイルの移動エラー", -"Error" => "エラー", "Name" => "名前", "Size" => "サイズ", "Modified" => "更新日時", diff --git a/apps/files/l10n/jv.php b/apps/files/l10n/jv.php new file mode 100644 index 0000000000000000000000000000000000000000..cfab5af7d1c5e0eba19a0eb99c7a95cb9ff40fa7 --- /dev/null +++ b/apps/files/l10n/jv.php @@ -0,0 +1,8 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), +"Download" => "Njipuk" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ka_GE.php b/apps/files/l10n/ka_GE.php index 230c2e4ede223f703ed4badf088891b282749bfe..f9749d72bb4b87bf0d75546daa853b3eef8d4459 100644 --- a/apps/files/l10n/ka_GE.php +++ b/apps/files/l10n/ka_GE.php @@ -21,16 +21,14 @@ $TRANSLATIONS = array( "Share" => "გაზიარება", "Delete permanently" => "სრულად წაშლა", "Rename" => "გადარქმევა", +"Error" => "შეცდომა", "Pending" => "მოცდის რეჟიმში", -"replaced {new_name} with {old_name}" => "{new_name} შეცვლილია {old_name}–ით", -"undo" => "დაბრუნება", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), "Your storage is full, files can not be updated or synced anymore!" => "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!", "Your storage is almost full ({usedSpacePercent}%)" => "თქვენი საცავი თითქმის გადაივსო ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "გადმოწერის მოთხოვნა მუშავდება. ის მოითხოვს გარკვეულ დროს რაგდან ფაილები არის დიდი ზომის.", -"Error" => "შეცდომა", "Name" => "სახელი", "Size" => "ზომა", "Modified" => "შეცვლილია", diff --git a/apps/files/l10n/km.php b/apps/files/l10n/km.php index 702c811ecf2d4e5402461656a73f52a38b396026..a7a01ccab9da7dfdcc58c0a73b53bf501ab573c5 100644 --- a/apps/files/l10n/km.php +++ b/apps/files/l10n/km.php @@ -2,11 +2,10 @@ $TRANSLATIONS = array( "Files" => "ឯកសារ", "Share" => "ចែក​រំលែក", -"undo" => "មិន​ធ្វើ​វិញ", +"Error" => "កំហុស", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), -"Error" => "កំហុស", "Name" => "ឈ្មោះ", "Size" => "ទំហំ", "Upload" => "ផ្ទុក​ឡើង", diff --git a/apps/files/l10n/ko.php b/apps/files/l10n/ko.php index 92a2578074c150840bdc38c736e96caaf8dd993c..c0f0d7d4454d26e8bfcdb35f4a34ecda2ed7159f 100644 --- a/apps/files/l10n/ko.php +++ b/apps/files/l10n/ko.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "공유", "Delete permanently" => "영구히 삭제", "Rename" => "이름 바꾸기", +"Error moving file" => "파일 이동 오류", +"Error" => "오류", "Pending" => "대기 중", "Could not rename file" => "이름을 변경할 수 없음", -"replaced {new_name} with {old_name}" => "{old_name}이(가) {new_name}(으)로 대체됨", -"undo" => "실행 취소", "Error deleting file." => "파일 삭제 오류.", "_%n folder_::_%n folders_" => array("폴더 %n개"), "_%n file_::_%n files_" => array("파일 %n개"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "암호화 앱의 개인 키가 잘못되었습니다. 암호화된 파일에 다시 접근하려면 개인 설정에서 개인 키 암호를 업데이트해야 합니다.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "암호화는 해제되어 있지만, 파일은 아직 암호화되어 있습니다. 개인 설정에서 파일을 복호화하십시오.", "Your download is being prepared. This might take some time if the files are big." => "다운로드 준비 중입니다. 파일 크기가 크면 시간이 오래 걸릴 수도 있습니다.", -"Error moving file" => "파일 이동 오류", -"Error" => "오류", "Name" => "이름", "Size" => "크기", "Modified" => "수정됨", diff --git a/apps/files/l10n/ku_IQ.php b/apps/files/l10n/ku_IQ.php index c0141656f5dd731e9cd11164998f660bf298783c..6ec5819d380ed4a9748ae791b057d54072c82e00 100644 --- a/apps/files/l10n/ku_IQ.php +++ b/apps/files/l10n/ku_IQ.php @@ -2,10 +2,10 @@ $TRANSLATIONS = array( "Files" => "په‌ڕگەکان", "Share" => "هاوبەشی کردن", +"Error" => "هه‌ڵه", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "هه‌ڵه", "Name" => "ناو", "Upload" => "بارکردن", "Save" => "پاشکه‌وتکردن", diff --git a/apps/files/l10n/lb.php b/apps/files/l10n/lb.php index 822ca7e2d02318b377ab6a86495114fe5447a51a..38b5d672d02e3c54be931fffe8595c0dd9e8d25f 100644 --- a/apps/files/l10n/lb.php +++ b/apps/files/l10n/lb.php @@ -11,11 +11,10 @@ $TRANSLATIONS = array( "File upload is in progress. Leaving the page now will cancel the upload." => "File Upload am gaang. Wann's de des Säit verléiss gëtt den Upload ofgebrach.", "Share" => "Deelen", "Rename" => "Ëm-benennen", -"undo" => "réckgängeg man", +"Error" => "Fehler", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "Fehler", "Name" => "Numm", "Size" => "Gréisst", "Modified" => "Geännert", diff --git a/apps/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php index 14c48621174e41d55ba1b014890d1a381847338f..50097e5f3624d5f899f1515dbdea3df60551dbf5 100644 --- a/apps/files/l10n/lt_LT.php +++ b/apps/files/l10n/lt_LT.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Dalintis", "Delete permanently" => "Ištrinti negrįžtamai", "Rename" => "Pervadinti", +"Error moving file" => "Klaida perkeliant failą", +"Error" => "Klaida", "Pending" => "Laukiantis", "Could not rename file" => "Neįmanoma pervadinti failo", -"replaced {new_name} with {old_name}" => "pakeiskite {new_name} į {old_name}", -"undo" => "anuliuoti", "Error deleting file." => "Klaida trinant failą.", "_%n folder_::_%n folders_" => array("%n aplankas","%n aplankai","%n aplankų"), "_%n file_::_%n files_" => array("%n failas","%n failai","%n failų"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Netinkamas privatus raktas Šifravimo programai. Prašome atnaujinti savo privataus rakto slaptažodį asmeniniuose nustatymuose, kad atkurti prieigą prie šifruotų failų.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Šifravimas buvo išjungtas, bet Jūsų failai vis dar užšifruoti. Prašome eiti į asmeninius nustatymus ir iššifruoti savo failus.", "Your download is being prepared. This might take some time if the files are big." => "Jūsų atsisiuntimas yra paruošiamas. tai gali užtrukti jei atsisiunčiamas didelis failas.", -"Error moving file" => "Klaida perkeliant failą", -"Error" => "Klaida", "Name" => "Pavadinimas", "Size" => "Dydis", "Modified" => "Pakeista", diff --git a/apps/files/l10n/lv.php b/apps/files/l10n/lv.php index 0d2ebf281abd26f52fb96f9e2df45753e631f2c3..fcb1a59aa38ba5f2f9bd3247c3e45ae85b16e558 100644 --- a/apps/files/l10n/lv.php +++ b/apps/files/l10n/lv.php @@ -23,9 +23,8 @@ $TRANSLATIONS = array( "Share" => "Dalīties", "Delete permanently" => "Dzēst pavisam", "Rename" => "Pārsaukt", +"Error" => "Kļūda", "Pending" => "Gaida savu kārtu", -"replaced {new_name} with {old_name}" => "aizvietoja {new_name} ar {old_name}", -"undo" => "atsaukt", "_%n folder_::_%n folders_" => array("%n mapes","%n mape","%n mapes"), "_%n file_::_%n files_" => array("%n faili","%n fails","%n faili"), "_Uploading %n file_::_Uploading %n files_" => array("%n","Augšupielāde %n failu","Augšupielāde %n failus"), @@ -33,7 +32,6 @@ $TRANSLATIONS = array( "Your storage is almost full ({usedSpacePercent}%)" => "Jūsu krātuve ir gandrīz pilna ({usedSpacePercent}%)", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Šifrēšana tika atslēgta, tomēr jūsu faili joprojām ir šifrēti. Atšifrēt failus var Personiskajos uzstādījumos.", "Your download is being prepared. This might take some time if the files are big." => "Tiek sagatavota lejupielāde. Tas var aizņemt kādu laiciņu, ja datnes ir lielas.", -"Error" => "Kļūda", "Name" => "Nosaukums", "Size" => "Izmērs", "Modified" => "Mainīts", diff --git a/apps/files/l10n/mk.php b/apps/files/l10n/mk.php index bc9ee15823c05cb754e3a2acab116087d298a8e5..fa6efd1aff3cdd82ff2f0c4d53d076ac863440ae 100644 --- a/apps/files/l10n/mk.php +++ b/apps/files/l10n/mk.php @@ -34,10 +34,10 @@ $TRANSLATIONS = array( "Share" => "Сподели", "Delete permanently" => "Трајно избришани", "Rename" => "Преименувај", +"Error moving file" => "Грешка при префрлање на датотека", +"Error" => "Грешка", "Pending" => "Чека", "Could not rename file" => "Не можам да ја преименувам датотеката", -"replaced {new_name} with {old_name}" => "заменета {new_name} со {old_name}", -"undo" => "врати", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "{dirs} and {files}" => "{dirs} и {files}", @@ -45,8 +45,6 @@ $TRANSLATIONS = array( "Your storage is full, files can not be updated or synced anymore!" => "Вашиот сториџ е полн, датотеките веќе не можат да се освежуваат или синхронизираат!", "Your storage is almost full ({usedSpacePercent}%)" => "Вашиот сториџ е скоро полн ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Вашето преземање се подготвува. Ова може да потрае до колку датотеките се големи.", -"Error moving file" => "Грешка при префрлање на датотека", -"Error" => "Грешка", "Name" => "Име", "Size" => "Големина", "Modified" => "Променето", diff --git a/apps/files/l10n/ms_MY.php b/apps/files/l10n/ms_MY.php index 0a7a50abb1a0d7b4d4eeb80d57cd03263c1abc9c..df0054c3d00b8affc289684e8142253cf76f89df 100644 --- a/apps/files/l10n/ms_MY.php +++ b/apps/files/l10n/ms_MY.php @@ -11,11 +11,11 @@ $TRANSLATIONS = array( "Upload cancelled." => "Muatnaik dibatalkan.", "Share" => "Kongsi", "Rename" => "Namakan", +"Error" => "Ralat", "Pending" => "Dalam proses", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), -"Error" => "Ralat", "Name" => "Nama", "Size" => "Saiz", "Modified" => "Dimodifikasi", diff --git a/apps/files/l10n/nb_NO.php b/apps/files/l10n/nb_NO.php index b90bee38f998d0307d8accf410ffd5ad2bf35af7..f1e2c2edeeb66d93ca08dcc5a38ce2dcb3e6d618 100644 --- a/apps/files/l10n/nb_NO.php +++ b/apps/files/l10n/nb_NO.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Del", "Delete permanently" => "Slett permanent", "Rename" => "Gi nytt navn", +"Error moving file" => "Feil ved flytting av fil", +"Error" => "Feil", "Pending" => "Ventende", "Could not rename file" => "Klarte ikke å gi nytt navn til fil", -"replaced {new_name} with {old_name}" => "erstattet {new_name} med {old_name}", -"undo" => "angre", "Error deleting file." => "Feil ved sletting av fil.", "_%n folder_::_%n folders_" => array("%n mappe","%n mapper"), "_%n file_::_%n files_" => array("%n fil","%n filer"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Ugyldig privat nøkkel for Krypterings-app. Oppdater passordet for din private nøkkel i dine personlige innstillinger for å gjenopprette tilgang til de krypterte filene dine.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Kryptering ble slått av men filene dine er fremdeles kryptert. Gå til dine personlige innstillinger for å dekryptere filene dine.", "Your download is being prepared. This might take some time if the files are big." => "Nedlastingen din klargjøres. Hvis filene er store kan dette ta litt tid.", -"Error moving file" => "Feil ved flytting av fil", -"Error" => "Feil", "Name" => "Navn", "Size" => "Størrelse", "Modified" => "Endret", diff --git a/apps/files/l10n/nl.php b/apps/files/l10n/nl.php index c617f0bfddea053e70e54cbb3455641686d61b34..946c7905b23b2bf9026a9686c9d9ea31ae83c9b3 100644 --- a/apps/files/l10n/nl.php +++ b/apps/files/l10n/nl.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Delen", "Delete permanently" => "Verwijder definitief", "Rename" => "Hernoem", +"Error moving file" => "Fout bij verplaatsen bestand", +"Error" => "Fout", "Pending" => "In behandeling", "Could not rename file" => "Kon niet hernoemen bestand", -"replaced {new_name} with {old_name}" => "verving {new_name} met {old_name}", -"undo" => "ongedaan maken", "Error deleting file." => "Fout bij verwijderen bestand.", "_%n folder_::_%n folders_" => array("","%n mappen"), "_%n file_::_%n files_" => array("","%n bestanden"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "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 was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Encryptie is uitgeschakeld maar uw bestanden zijn nog steeds versleuteld. Ga naar uw persoonlijke instellingen om uw bestanden te decoderen.", "Your download is being prepared. This might take some time if the files are big." => "Uw download wordt voorbereid. Dit kan enige tijd duren bij grote bestanden.", -"Error moving file" => "Fout bij verplaatsen bestand", -"Error" => "Fout", "Name" => "Naam", "Size" => "Grootte", "Modified" => "Aangepast", diff --git a/apps/files/l10n/nn_NO.php b/apps/files/l10n/nn_NO.php index 4f74167d9adfdd36243f2c38e4318d3d6d1d8e6a..bd17fa3386a5512332fc92f1a4e299429a924f2e 100644 --- a/apps/files/l10n/nn_NO.php +++ b/apps/files/l10n/nn_NO.php @@ -27,9 +27,9 @@ $TRANSLATIONS = array( "Share" => "Del", "Delete permanently" => "Slett for godt", "Rename" => "Endra namn", +"Error moving file" => "Feil ved flytting av fil", +"Error" => "Feil", "Pending" => "Under vegs", -"replaced {new_name} with {old_name}" => "bytte ut {new_name} med {old_name}", -"undo" => "angre", "_%n folder_::_%n folders_" => array("%n mappe","%n mapper"), "_%n file_::_%n files_" => array("%n fil","%n filer"), "{dirs} and {files}" => "{dirs} og {files}", @@ -38,8 +38,6 @@ $TRANSLATIONS = array( "Your storage is almost full ({usedSpacePercent}%)" => "Lagringa di er nesten full ({usedSpacePercent} %)", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Kryptering er skrudd av, men filene dine er enno krypterte. Du kan dekryptera filene i personlege innstillingar.", "Your download is being prepared. This might take some time if the files are big." => "Gjer klar nedlastinga di. Dette kan ta ei stund viss filene er store.", -"Error moving file" => "Feil ved flytting av fil", -"Error" => "Feil", "Name" => "Namn", "Size" => "Storleik", "Modified" => "Endra", diff --git a/apps/files/l10n/oc.php b/apps/files/l10n/oc.php index eb1a9038b0839ad15ffeec68fb6bd22d2adb193a..7a24c81974ec9f435b11f383f2f454ce091d8df7 100644 --- a/apps/files/l10n/oc.php +++ b/apps/files/l10n/oc.php @@ -11,12 +11,11 @@ $TRANSLATIONS = array( "File upload is in progress. Leaving the page now will cancel the upload." => "Un amontcargar es a se far. Daissar aquesta pagina ara tamparà lo cargament. ", "Share" => "Parteja", "Rename" => "Torna nomenar", +"Error" => "Error", "Pending" => "Al esperar", -"undo" => "defar", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "Error", "Name" => "Nom", "Size" => "Talha", "Modified" => "Modificat", diff --git a/apps/files/l10n/pa.php b/apps/files/l10n/pa.php index 63fcbe12ddaa1a89d79c12bfc1eea4ca64ce8c53..b18d2071e080a9fdd0b9fbf424c5710e7248a923 100644 --- a/apps/files/l10n/pa.php +++ b/apps/files/l10n/pa.php @@ -3,11 +3,10 @@ $TRANSLATIONS = array( "Files" => "ਫਾਇਲਾਂ", "Share" => "ਸਾਂਝਾ ਕਰੋ", "Rename" => "ਨਾਂ ਬਦਲੋ", -"undo" => "ਵਾਪਸ", +"Error" => "ਗਲਤੀ", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "ਗਲਤੀ", "Upload" => "ਅੱਪਲੋਡ", "Cancel upload" => "ਅੱਪਲੋਡ ਰੱਦ ਕਰੋ", "Download" => "ਡਾਊਨਲੋਡ", diff --git a/apps/files/l10n/pl.php b/apps/files/l10n/pl.php index 3e93dc881e99ad9fab5e52326dd94cdd6bd45e02..83126b3ea035367c8f4868e874b1392971482eeb 100644 --- a/apps/files/l10n/pl.php +++ b/apps/files/l10n/pl.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Udostępnij", "Delete permanently" => "Trwale usuń", "Rename" => "Zmień nazwę", +"Error moving file" => "Błąd prz przenoszeniu pliku", +"Error" => "Błąd", "Pending" => "Oczekujące", "Could not rename file" => "Nie można zmienić nazwy pliku", -"replaced {new_name} with {old_name}" => "zastąpiono {new_name} przez {old_name}", -"undo" => "cofnij", "Error deleting file." => "Błąd podczas usuwania pliku", "_%n folder_::_%n folders_" => array("%n katalog","%n katalogi","%n katalogów"), "_%n file_::_%n files_" => array("%n plik","%n pliki","%n plików"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Klucz prywatny nie jest poprawny! Może Twoje hasło zostało zmienione z zewnątrz. Można zaktualizować hasło klucza prywatnego w ustawieniach osobistych w celu odzyskania dostępu do plików", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Szyfrowanie zostało wyłączone, ale nadal pliki są zaszyfrowane. Przejdź do ustawień osobistych i tam odszyfruj pliki.", "Your download is being prepared. This might take some time if the files are big." => "Pobieranie jest przygotowywane. Może to zająć trochę czasu jeśli pliki są duże.", -"Error moving file" => "Błąd prz przenoszeniu pliku", -"Error" => "Błąd", "Name" => "Nazwa", "Size" => "Rozmiar", "Modified" => "Modyfikacja", diff --git a/apps/files/l10n/pl_PL.php b/apps/files/l10n/pl_PL.php deleted file mode 100644 index b67f67b972e26e1a1ca7cb514b240285adbf1e62..0000000000000000000000000000000000000000 --- a/apps/files/l10n/pl_PL.php +++ /dev/null @@ -1,5 +0,0 @@ - "Zapisz" -); -$PLURAL_FORMS = "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/files/l10n/pt_BR.php b/apps/files/l10n/pt_BR.php index d0c27431daaf4c89c6321dd0d2a3831b8e51a9bb..48c32e8887f6bb8d9b7f32ec98a5eb9d3d72d0cf 100644 --- a/apps/files/l10n/pt_BR.php +++ b/apps/files/l10n/pt_BR.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Compartilhar", "Delete permanently" => "Excluir permanentemente", "Rename" => "Renomear", +"Error moving file" => "Erro movendo o arquivo", +"Error" => "Erro", "Pending" => "Pendente", "Could not rename file" => "Não foi possível renomear o arquivo", -"replaced {new_name} with {old_name}" => "Substituído {old_name} por {new_name} ", -"undo" => "desfazer", "Error deleting file." => "Erro eliminando o arquivo.", "_%n folder_::_%n folders_" => array("%n pasta","%n pastas"), "_%n file_::_%n files_" => array("%n arquivo","%n arquivos"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Chave do App de Encriptação é inválida. Por favor, atualize sua senha de chave privada em suas configurações pessoais para recuperar o acesso a seus arquivos criptografados.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Encriptação foi desabilitada mas seus arquivos continuam encriptados. Por favor vá a suas configurações pessoais para descriptar seus arquivos.", "Your download is being prepared. This might take some time if the files are big." => "Seu download está sendo preparado. Isto pode levar algum tempo se os arquivos forem grandes.", -"Error moving file" => "Erro movendo o arquivo", -"Error" => "Erro", "Name" => "Nome", "Size" => "Tamanho", "Modified" => "Modificado", diff --git a/apps/files/l10n/pt_PT.php b/apps/files/l10n/pt_PT.php index 3b3c2f842bd16c61aa7b92b438de043496d91fad..0afb6b501570cf9d5a6e8875ecc5328ebf81dc3f 100644 --- a/apps/files/l10n/pt_PT.php +++ b/apps/files/l10n/pt_PT.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "Partilhar", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renomear", +"Error moving file" => "Erro ao mover o ficheiro", +"Error" => "Erro", "Pending" => "Pendente", "Could not rename file" => "Não pôde renomear o ficheiro", -"replaced {new_name} with {old_name}" => "substituido {new_name} por {old_name}", -"undo" => "desfazer", "Error deleting file." => "Erro ao apagar o ficheiro.", "_%n folder_::_%n folders_" => array("%n pasta","%n pastas"), "_%n file_::_%n files_" => array("%n ficheiro","%n ficheiros"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Chave privada inválida da Aplicação de Encriptação. Por favor atualize a sua senha de chave privada nas definições pessoais, para recuperar o acesso aos seus ficheiros encriptados.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "A encriptação foi desactivada mas os seus ficheiros continuam encriptados. Por favor consulte as suas definições pessoais para desencriptar os ficheiros.", "Your download is being prepared. This might take some time if the files are big." => "O seu download está a ser preparado. Este processo pode demorar algum tempo se os ficheiros forem grandes.", -"Error moving file" => "Erro ao mover o ficheiro", -"Error" => "Erro", "Name" => "Nome", "Size" => "Tamanho", "Modified" => "Modificado", diff --git a/apps/files/l10n/ro.php b/apps/files/l10n/ro.php index 7686025e35c9a41e33c026b2f5cd39b40acc52f5..6cda724df430f38fccd16b7478edc48867796db3 100644 --- a/apps/files/l10n/ro.php +++ b/apps/files/l10n/ro.php @@ -4,7 +4,9 @@ $TRANSLATIONS = array( "Could not move %s" => "Nu se poate muta %s", "File name cannot be empty." => "Numele fișierului nu poate rămâne gol.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nume nevalide, '\\', '/', '<', '>', ':', '\"', '|', '?' și '*' nu sunt permise.", +"Error while downloading %s to %s" => "Eroare la descarcarea %s in %s", "Error when creating the file" => "Eroare la crearea fisierului", +"Folder name cannot be empty." => "Numele folderului nu poate fi liber.", "Error when creating the folder" => "Eroare la crearea folderului", "Unable to set upload directory." => "Imposibil de a seta directorul pentru incărcare.", "Invalid Token" => "Jeton Invalid", @@ -32,10 +34,10 @@ $TRANSLATIONS = array( "Share" => "Partajează", "Delete permanently" => "Șterge permanent", "Rename" => "Redenumește", +"Error moving file" => "Eroare la mutarea fișierului", +"Error" => "Eroare", "Pending" => "În așteptare", "Could not rename file" => "Nu s-a putut redenumi fisierul", -"replaced {new_name} with {old_name}" => "{new_name} a fost înlocuit cu {old_name}", -"undo" => "desfă", "_%n folder_::_%n folders_" => array("%n director","%n directoare","%n directoare"), "_%n file_::_%n files_" => array("%n fișier","%n fișiere","%n fișiere"), "{dirs} and {files}" => "{dirs} și {files}", @@ -44,8 +46,6 @@ $TRANSLATIONS = array( "Your storage is almost full ({usedSpacePercent}%)" => "Spațiul de stocare este aproape plin ({usedSpacePercent}%)", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "criptarea a fost disactivata dar fisierele sant inca criptate.va rog intrati in setarile personale pentru a decripta fisierele", "Your download is being prepared. This might take some time if the files are big." => "Se pregătește descărcarea. Aceasta poate dura ceva timp dacă fișierele sunt mari.", -"Error moving file" => "Eroare la mutarea fișierului", -"Error" => "Eroare", "Name" => "Nume", "Size" => "Mărime", "Modified" => "Modificat", diff --git a/apps/files/l10n/ru.php b/apps/files/l10n/ru.php index 2c0335f3cc302ad26cd1930cf0ae5ba2c45c3b4f..17f06c6a2008aa083e3f40549c8e103c63e36f70 100644 --- a/apps/files/l10n/ru.php +++ b/apps/files/l10n/ru.php @@ -3,7 +3,9 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Невозможно переместить %s - файл с таким именем уже существует", "Could not move %s" => "Невозможно переместить %s", "File name cannot be empty." => "Имя файла не может быть пустым.", +"\"%s\" is an invalid file name." => "\"%s\" это не правильное имя файла.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неправильное имя: символы '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' недопустимы.", +"The target folder has been moved or deleted." => "Целевой каталог был перемещен или удален.", "The name %s is already used in the folder %s. Please choose a different name." => "Имя %s уже используется для каталога %s. Пожалуйста, выберите другое имя.", "Not a valid source" => "Неправильный источник", "Server is not allowed to open URLs, please check the server configuration" => "Сервер не позволяет открывать URL-адреса, пожалуйста, проверьте настройки сервера", @@ -27,6 +29,8 @@ $TRANSLATIONS = array( "Invalid directory." => "Неверный каталог.", "Files" => "Файлы", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Невозможно загрузить {filename}, так как это либо каталог, либо файл нулевого размера", +"Total file size {size1} exceeds upload limit {size2}" => "Полный размер файла {size1} превышает лимит по загрузке {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Не достаточно свободного места, Вы загружаете {size1} но осталось только {size2}", "Upload cancelled." => "Загрузка отменена.", "Could not get result from server." => "Не удалось получить ответ от сервера.", "File upload is in progress. Leaving the page now will cancel the upload." => "Идёт загрузка файла. Покинув страницу, вы прервёте загрузку.", @@ -39,23 +43,22 @@ $TRANSLATIONS = array( "Share" => "Открыть доступ", "Delete permanently" => "Удалить окончательно", "Rename" => "Переименовать", +"Error moving file" => "Ошибка при перемещении файла", +"Error" => "Ошибка", "Pending" => "Ожидание", "Could not rename file" => "Не удалось переименовать файл", -"replaced {new_name} with {old_name}" => "заменено {new_name} на {old_name}", -"undo" => "отмена", "Error deleting file." => "Ошибка при удалении файла.", "_%n folder_::_%n folders_" => array("%n каталог","%n каталога","%n каталогов"), "_%n file_::_%n files_" => array("%n файл","%n файла","%n файлов"), "{dirs} and {files}" => "{dirs} и {files}", "_Uploading %n file_::_Uploading %n files_" => array("Закачка %n файла","Закачка %n файлов","Закачка %n файлов"), +"\"{name}\" is an invalid file name." => "\"{name}\" это не правильное имя файла.", "Your storage is full, files can not be updated or synced anymore!" => "Ваше хранилище заполнено, произведите очистку перед загрузкой новых файлов.", "Your storage is almost full ({usedSpacePercent}%)" => "Ваше хранилище почти заполнено ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Приложение для шифрования активно, но ваши ключи не инициализированы, пожалуйста, перелогиньтесь", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Закрытый ключ приложения шифрования недействителен. Обновите закрытый ключ в личных настройках, чтобы восстановить доступ к зашифрованным файлам.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Шифрование было отключено, но ваши файлы остались зашифрованными. Зайдите на страницу личных настроек для того, чтобы расшифровать их.", "Your download is being prepared. This might take some time if the files are big." => "Идёт подготовка к скачиванию. Это может занять некоторое время, если файлы большого размера.", -"Error moving file" => "Ошибка при перемещении файла", -"Error" => "Ошибка", "Name" => "Имя", "Size" => "Размер", "Modified" => "Дата изменения", diff --git a/apps/files/l10n/si_LK.php b/apps/files/l10n/si_LK.php index 44decfef1b023155bd2a50477553ede12a18692a..a2809ee2f5d834d5540a7101cbfc9e4bafacc488 100644 --- a/apps/files/l10n/si_LK.php +++ b/apps/files/l10n/si_LK.php @@ -12,11 +12,10 @@ $TRANSLATIONS = array( "File upload is in progress. Leaving the page now will cancel the upload." => "උඩුගතකිරීමක් සිදුවේ. පිටුව හැර යාමෙන් එය නැවතෙනු ඇත", "Share" => "බෙදා හදා ගන්න", "Rename" => "නැවත නම් කරන්න", -"undo" => "නිෂ්ප්‍රභ කරන්න", +"Error" => "දෝෂයක්", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "දෝෂයක්", "Name" => "නම", "Size" => "ප්‍රමාණය", "Modified" => "වෙනස් කළ", diff --git a/apps/files/l10n/sk_SK.php b/apps/files/l10n/sk_SK.php index e80ca0186cbd010698328f12316eeb4403877a96..cffb89c294d1a71379e711a95092b76e65ed20c6 100644 --- a/apps/files/l10n/sk_SK.php +++ b/apps/files/l10n/sk_SK.php @@ -3,7 +3,9 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Nie je možné presunúť %s - súbor s týmto menom už existuje", "Could not move %s" => "Nie je možné presunúť %s", "File name cannot be empty." => "Meno súboru nemôže byť prázdne", +"\"%s\" is an invalid file name." => "\"%s\" je neplatné meno súboru.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nesprávne meno, '\\', '/', '<', '>', ':', '\"', '|', '?' a '*' nie sú povolené hodnoty.", +"The target folder has been moved or deleted." => "Cieľový priečinok bol premiestnený alebo odstránený.", "The name %s is already used in the folder %s. Please choose a different name." => "Názov %s už používa priečinok s%. Prosím zvoľte iný názov.", "Not a valid source" => "Neplatný zdroj", "Server is not allowed to open URLs, please check the server configuration" => "Server nie je oprávnený otvárať adresy URL. Overte nastavenia servera.", @@ -27,6 +29,8 @@ $TRANSLATIONS = array( "Invalid directory." => "Neplatný priečinok.", "Files" => "Súbory", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Nemožno nahrať súbor {filename}, pretože je to priečinok, alebo má 0 bitov", +"Total file size {size1} exceeds upload limit {size2}" => "Celková veľkosť súboru {size1} prekračuje upload limit {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Nie je dostatok voľného miesta, chcete nahrať {size1} ale k dispozíciji je len {size2}", "Upload cancelled." => "Odosielanie zrušené.", "Could not get result from server." => "Nepodarilo sa dostať výsledky zo servera.", "File upload is in progress. Leaving the page now will cancel the upload." => "Opustenie stránky zruší práve prebiehajúce odosielanie súboru.", @@ -39,23 +43,22 @@ $TRANSLATIONS = array( "Share" => "Zdieľať", "Delete permanently" => "Zmazať trvalo", "Rename" => "Premenovať", +"Error moving file" => "Chyba pri presúvaní súboru", +"Error" => "Chyba", "Pending" => "Prebieha", "Could not rename file" => "Nemožno premenovať súbor", -"replaced {new_name} with {old_name}" => "prepísaný {new_name} súborom {old_name}", -"undo" => "vrátiť", "Error deleting file." => "Chyba pri mazaní súboru.", "_%n folder_::_%n folders_" => array("%n priečinok","%n priečinky","%n priečinkov"), "_%n file_::_%n files_" => array("%n súbor","%n súbory","%n súborov"), "{dirs} and {files}" => "{dirs} a {files}", "_Uploading %n file_::_Uploading %n files_" => array("Nahrávam %n súbor","Nahrávam %n súbory","Nahrávam %n súborov"), +"\"{name}\" is an invalid file name." => "\"{name}\" je neplatné meno súboru.", "Your storage is full, files can not be updated or synced anymore!" => "Vaše úložisko je plné. Súbory nemožno aktualizovať ani synchronizovať!", "Your storage is almost full ({usedSpacePercent}%)" => "Vaše úložisko je takmer plné ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Aplikácia na šifrovanie je zapnutá, ale vaše kľúče nie sú inicializované. Odhláste sa a znovu sa prihláste.", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Chybný súkromný kľúč na šifrovanie aplikácií. Zaktualizujte si heslo súkromného kľúča v svojom osobnom nastavení, aby ste znovu získali prístup k svojim zašifrovaným súborom.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Šifrovanie bolo zakázané, ale vaše súbory sú stále zašifrované. Prosím, choďte do osobného nastavenia pre dešifrovanie súborov.", "Your download is being prepared. This might take some time if the files are big." => "Vaše sťahovanie sa pripravuje. Ak sú sťahované súbory veľké, môže to chvíľu trvať.", -"Error moving file" => "Chyba pri presúvaní súboru", -"Error" => "Chyba", "Name" => "Názov", "Size" => "Veľkosť", "Modified" => "Upravené", diff --git a/apps/files/l10n/sl.php b/apps/files/l10n/sl.php index ae54ace12da9b79fb64871c45666e2eada50a2f2..fcb358bd7bd71e2856765871f1cbcdae9641d95e 100644 --- a/apps/files/l10n/sl.php +++ b/apps/files/l10n/sl.php @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Souporaba", "Delete permanently" => "Izbriši dokončno", "Rename" => "Preimenuj", +"Error moving file" => "Napaka premikanja datoteke", +"Error" => "Napaka", "Pending" => "V čakanju ...", "Could not rename file" => "Ni mogoče preimenovati datoteke", -"replaced {new_name} with {old_name}" => "preimenovano ime {new_name} z imenom {old_name}", -"undo" => "razveljavi", "Error deleting file." => "Napaka brisanja datoteke.", "_%n folder_::_%n folders_" => array("%n mapa","%n mapi","%n mape","%n map"), "_%n file_::_%n files_" => array("%n datoteka","%n datoteki","%n datoteke","%n datotek"), @@ -59,8 +59,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Ni ustreznega osebnega ključa za program za šifriranje. Posodobite osebni ključ za dostop do šifriranih datotek med nastavitvami.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Šifriranje je onemogočeno, datoteke pa so še vedno šifrirane. Odšifrirajte jih med nastavitvami.", "Your download is being prepared. This might take some time if the files are big." => "Postopek priprave datoteke za prejem je lahko dolgotrajen, kadar je datoteka zelo velika.", -"Error moving file" => "Napaka premikanja datoteke", -"Error" => "Napaka", "Name" => "Ime", "Size" => "Velikost", "Modified" => "Spremenjeno", diff --git a/apps/files/l10n/sq.php b/apps/files/l10n/sq.php index 073f2def624db2c60f3182e2b29894478c998686..ade4f769faa3739009f359e8d465548dcb4895b5 100644 --- a/apps/files/l10n/sq.php +++ b/apps/files/l10n/sq.php @@ -25,9 +25,9 @@ $TRANSLATIONS = array( "Share" => "Ndaj", "Delete permanently" => "Fshi përfundimisht", "Rename" => "Riemëro", +"Error moving file" => "Gabim lëvizjen dokumentave", +"Error" => "Gabim", "Pending" => "Në vijim", -"replaced {new_name} with {old_name}" => "u zëvendësua {new_name} me {old_name}", -"undo" => "anullo", "_%n folder_::_%n folders_" => array("%n dosje","%n dosje"), "_%n file_::_%n files_" => array("%n skedar","%n skedarë"), "{dirs} and {files}" => "{dirs} dhe {files}", @@ -36,8 +36,6 @@ $TRANSLATIONS = array( "Your storage is almost full ({usedSpacePercent}%)" => "Hapsira juaj e arkivimit është pothuajse në fund ({usedSpacePercent}%)", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Kodifikimi u çaktivizua por skedarët tuaj vazhdojnë të jenë të kodifikuar. Ju lutem shkoni tek parametrat personale për të dekodifikuar skedarët tuaj.", "Your download is being prepared. This might take some time if the files are big." => "Shkarkimi juaj është duke u përgatitur. Kjo mund të kërkojë kohë nëse skedarët janë të mëdhenj.", -"Error moving file" => "Gabim lëvizjen dokumentave", -"Error" => "Gabim", "Name" => "Emri", "Size" => "Madhësia", "Modified" => "Ndryshuar", diff --git a/apps/files/l10n/sr.php b/apps/files/l10n/sr.php index 2a1b478b2aeed6c81da0bf8cb2a63599bf4e2150..44669e8167aaf574c575070ce0e4dca6a3c63ab9 100644 --- a/apps/files/l10n/sr.php +++ b/apps/files/l10n/sr.php @@ -21,16 +21,14 @@ $TRANSLATIONS = array( "Share" => "Дели", "Delete permanently" => "Обриши за стално", "Rename" => "Преименуј", +"Error" => "Грешка", "Pending" => "На чекању", -"replaced {new_name} with {old_name}" => "замењено {new_name} са {old_name}", -"undo" => "опозови", "_%n folder_::_%n folders_" => array("","",""), "_%n file_::_%n files_" => array("","",""), "_Uploading %n file_::_Uploading %n files_" => array("","",""), "Your storage is full, files can not be updated or synced anymore!" => "Ваше складиште је пуно. Датотеке више не могу бити ажуриране ни синхронизоване.", "Your storage is almost full ({usedSpacePercent}%)" => "Ваше складиште је скоро па пуно ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Припремам преузимање. Ово може да потраје ако су датотеке велике.", -"Error" => "Грешка", "Name" => "Име", "Size" => "Величина", "Modified" => "Измењено", diff --git a/apps/files/l10n/sr@latin.php b/apps/files/l10n/sr@latin.php index 67bf30d8606e173fc1184d46a259bdd4db246224..a5c74860f78fd32d275b283d8cfbb8ea3852f6e6 100644 --- a/apps/files/l10n/sr@latin.php +++ b/apps/files/l10n/sr@latin.php @@ -8,10 +8,10 @@ $TRANSLATIONS = array( "Files" => "Fajlovi", "Share" => "Podeli", "Rename" => "Preimenij", +"Error" => "Greška", "_%n folder_::_%n folders_" => array("","",""), "_%n file_::_%n files_" => array("","",""), "_Uploading %n file_::_Uploading %n files_" => array("","",""), -"Error" => "Greška", "Name" => "Ime", "Size" => "Veličina", "Modified" => "Zadnja izmena", diff --git a/apps/files/l10n/sv.php b/apps/files/l10n/sv.php index fa88a1e966d54389c03df47fb18be475b6f993ce..f420216228cc29e2cb060a1aa087f239c1e11cd4 100644 --- a/apps/files/l10n/sv.php +++ b/apps/files/l10n/sv.php @@ -3,9 +3,12 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Kunde inte flytta %s - Det finns redan en fil med detta namn", "Could not move %s" => "Kan inte flytta %s", "File name cannot be empty." => "Filnamn kan inte vara tomt.", +"\"%s\" is an invalid file name." => "\"%s\" är ett ogiltigt filnamn.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ogiltigt namn, '\\', '/', '<', '>', ':', '\"', '|', '?' och '*' är inte tillåtet.", +"The target folder has been moved or deleted." => "Målmappen har flyttats eller tagits bort.", "The name %s is already used in the folder %s. Please choose a different name." => "Namnet %s används redan i katalogen %s. Välj ett annat namn.", "Not a valid source" => "Inte en giltig källa", +"Server is not allowed to open URLs, please check the server configuration" => "Servern är inte tillåten att öppna URL:er, vänligen kontrollera server konfigurationen", "Error while downloading %s to %s" => "Fel under nerladdning från %s till %s", "Error when creating the file" => "Fel under skapande utav filen", "Folder name cannot be empty." => "Katalognamn kan ej vara tomt.", @@ -26,6 +29,8 @@ $TRANSLATIONS = array( "Invalid directory." => "Felaktig mapp.", "Files" => "Filer", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Kan inte ladda upp {filename} eftersom den antingen är en mapp eller har 0 bytes.", +"Total file size {size1} exceeds upload limit {size2}" => "Totala filstorleken {size1} överskrider uppladdningsgränsen {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Inte tillräckligt med ledigt utrymme, du laddar upp {size1} men endast {size2} finns kvar.", "Upload cancelled." => "Uppladdning avbruten.", "Could not get result from server." => "Gick inte att hämta resultat från server.", "File upload is in progress. Leaving the page now will cancel the upload." => "Filuppladdning pågår. Lämnar du sidan så avbryts uppladdningen.", @@ -34,26 +39,26 @@ $TRANSLATIONS = array( "{new_name} already exists" => "{new_name} finns redan", "Could not create file" => "Kunde ej skapa fil", "Could not create folder" => "Kunde ej skapa katalog", +"Error fetching URL" => "Fel vid hämtning av URL", "Share" => "Dela", "Delete permanently" => "Radera permanent", "Rename" => "Byt namn", +"Error moving file" => "Fel uppstod vid flyttning av fil", +"Error" => "Fel", "Pending" => "Väntar", "Could not rename file" => "Kan ej byta filnamn", -"replaced {new_name} with {old_name}" => "ersatt {new_name} med {old_name}", -"undo" => "ångra", "Error deleting file." => "Kunde inte ta bort filen.", "_%n folder_::_%n folders_" => array("%n mapp","%n mappar"), "_%n file_::_%n files_" => array("%n fil","%n filer"), "{dirs} and {files}" => "{dirs} och {files}", "_Uploading %n file_::_Uploading %n files_" => array("Laddar upp %n fil","Laddar upp %n filer"), +"\"{name}\" is an invalid file name." => "\"{name}\" är ett ogiltligt filnamn.", "Your storage is full, files can not be updated or synced anymore!" => "Ditt lagringsutrymme är fullt, filer kan inte längre uppdateras eller synkroniseras!", "Your storage is almost full ({usedSpacePercent}%)" => "Ditt lagringsutrymme är nästan fullt ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Krypteringsprogrammet är aktiverat men dina nycklar är inte initierade. Vänligen logga ut och in igen", "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Ogiltig privat nyckel i krypteringsprogrammet. Vänligen uppdatera lösenordet till din privata nyckel under dina personliga inställningar för att återfå tillgång till dina krypterade filer.", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Kryptering inaktiverades men dina filer är fortfarande krypterade. Vänligen gå till sidan för dina personliga inställningar för att dekryptera dina filer.", "Your download is being prepared. This might take some time if the files are big." => "Din nedladdning förbereds. Det kan ta tid om det är stora filer.", -"Error moving file" => "Fel uppstod vid flyttning av fil", -"Error" => "Fel", "Name" => "Namn", "Size" => "Storlek", "Modified" => "Ändrad", @@ -69,6 +74,7 @@ $TRANSLATIONS = array( "Maximum input size for ZIP files" => "Största tillåtna storlek för ZIP-filer", "Save" => "Spara", "New" => "Ny", +"New text file" => "Ny textfil", "Text file" => "Textfil", "New folder" => "Ny mapp", "Folder" => "Mapp", diff --git a/apps/files/l10n/ta_LK.php b/apps/files/l10n/ta_LK.php index c0589feecea20090001037f9ca2fea59e77dea35..257aacf147170101c3761b9f69a19f44ab5d39cc 100644 --- a/apps/files/l10n/ta_LK.php +++ b/apps/files/l10n/ta_LK.php @@ -14,13 +14,11 @@ $TRANSLATIONS = array( "{new_name} already exists" => "{new_name} ஏற்கனவே உள்ளது", "Share" => "பகிர்வு", "Rename" => "பெயர்மாற்றம்", +"Error" => "வழு", "Pending" => "நிலுவையிலுள்ள", -"replaced {new_name} with {old_name}" => "{new_name} ஆனது {old_name} இனால் மாற்றப்பட்டது", -"undo" => "முன் செயல் நீக்கம் ", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "வழு", "Name" => "பெயர்", "Size" => "அளவு", "Modified" => "மாற்றப்பட்டது", diff --git a/apps/files/l10n/te.php b/apps/files/l10n/te.php index 155e4b5c201494f21650396d9419036cdea894d1..b2cf4c01d8a6175e7415859bfe4a5f8c4a50a07a 100644 --- a/apps/files/l10n/te.php +++ b/apps/files/l10n/te.php @@ -1,10 +1,10 @@ "శాశ్వతంగా తొలగించు", +"Error" => "పొరపాటు", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "పొరపాటు", "Name" => "పేరు", "Size" => "పరిమాణం", "Save" => "భద్రపరచు", diff --git a/apps/files/l10n/th_TH.php b/apps/files/l10n/th_TH.php index 110b84cad5e4f5c067e549112f21735a1496d2cc..8f5f15f2a34380c59798dad9f70385cd408a417e 100644 --- a/apps/files/l10n/th_TH.php +++ b/apps/files/l10n/th_TH.php @@ -20,16 +20,14 @@ $TRANSLATIONS = array( "{new_name} already exists" => "{new_name} มีอยู่แล้วในระบบ", "Share" => "แชร์", "Rename" => "เปลี่ยนชื่อ", +"Error" => "ข้อผิดพลาด", "Pending" => "อยู่ระหว่างดำเนินการ", -"replaced {new_name} with {old_name}" => "แทนที่ {new_name} ด้วย {old_name} แล้ว", -"undo" => "เลิกทำ", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), "Your storage is full, files can not be updated or synced anymore!" => "พื้นที่จัดเก็บข้อมูลของคุณเต็มแล้ว ไม่สามารถอัพเดทหรือผสานไฟล์ต่างๆได้อีกต่อไป", "Your storage is almost full ({usedSpacePercent}%)" => "พื้นที่จัดเก็บข้อมูลของคุณใกล้เต็มแล้ว ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "กำลังเตรียมดาวน์โหลดข้อมูล หากไฟล์มีขนาดใหญ่ อาจใช้เวลาสักครู่", -"Error" => "ข้อผิดพลาด", "Name" => "ชื่อ", "Size" => "ขนาด", "Modified" => "แก้ไขแล้ว", diff --git a/apps/files/l10n/tr.php b/apps/files/l10n/tr.php index a2570e002ac42bb773d6a93e5c17e6e8f153b32b..87c664cc17115590cab7ecfbb936f9ce2c1eebee 100644 --- a/apps/files/l10n/tr.php +++ b/apps/files/l10n/tr.php @@ -29,7 +29,7 @@ $TRANSLATIONS = array( "Invalid directory." => "Geçersiz dizin.", "Files" => "Dosyalar", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Bir dizin veya 0 bayt olduğundan {filename} yüklenemedi", -"Total file size {size1} exceeds upload limit {size2}" => "Toplam dosya boyutu {size1} gönderme sınırını {size2} aşıyor", +"Total file size {size1} exceeds upload limit {size2}" => "Toplam dosya boyutu {size1}, {size2} gönderme sınırını aşıyor", "Not enough free space, you are uploading {size1} but only {size2} is left" => "Yeterince boş alan yok. Gönderdiğiniz boyut {size1} ancak {size2} alan mevcut", "Upload cancelled." => "Yükleme iptal edildi.", "Could not get result from server." => "Sunucudan sonuç alınamadı.", @@ -43,10 +43,10 @@ $TRANSLATIONS = array( "Share" => "Paylaş", "Delete permanently" => "Kalıcı olarak sil", "Rename" => "İsim değiştir.", +"Error moving file" => "Dosya taşıma hatası", +"Error" => "Hata", "Pending" => "Bekliyor", "Could not rename file" => "Dosya adlandırılamadı", -"replaced {new_name} with {old_name}" => "{new_name} ismi {old_name} ile değiştirildi", -"undo" => "geri al", "Error deleting file." => "Dosya silinirken hata.", "_%n folder_::_%n folders_" => array("%n dizin","%n dizin"), "_%n file_::_%n files_" => array("%n dosya","%n dosya"), @@ -59,12 +59,10 @@ $TRANSLATIONS = array( "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 was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Şifreleme işlemi durduruldu ancak dosyalarınız şifreli. Dosyalarınızın şifresini kaldırmak için lütfen kişisel ayarlar kısmına geçin.", "Your download is being prepared. This might take some time if the files are big." => "İndirmeniz hazırlanıyor. Dosya büyük ise biraz zaman alabilir.", -"Error moving file" => "Dosya taşıma hatası", -"Error" => "Hata", "Name" => "İsim", "Size" => "Boyut", "Modified" => "Değiştirilme", -"Invalid folder name. Usage of 'Shared' is reserved." => "Geçersiz dizin adı. 'Shared' ismi ayrılmıştır.", +"Invalid folder name. Usage of 'Shared' is reserved." => "Geçersiz klasör adı. 'Shared' ismi ayrılmıştır.", "%s could not be renamed" => "%s yeniden adlandırılamadı", "Upload" => "Yükle", "File handling" => "Dosya işlemleri", diff --git a/apps/files/l10n/ug.php b/apps/files/l10n/ug.php index ee188d927ef933faab507c87b19db7cf727968f2..13354c153b2dfeeca420213507dffa9697fde4b4 100644 --- a/apps/files/l10n/ug.php +++ b/apps/files/l10n/ug.php @@ -13,12 +13,11 @@ $TRANSLATIONS = array( "Share" => "ھەمبەھىر", "Delete permanently" => "مەڭگۈلۈك ئۆچۈر", "Rename" => "ئات ئۆزگەرت", +"Error" => "خاتالىق", "Pending" => "كۈتۈۋاتىدۇ", -"undo" => "يېنىۋال", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), -"Error" => "خاتالىق", "Name" => "ئاتى", "Size" => "چوڭلۇقى", "Modified" => "ئۆزگەرتكەن", diff --git a/apps/files/l10n/uk.php b/apps/files/l10n/uk.php index b74126c446da604a08cac9e483b15afcb3244675..905d27c3ee25edde43e58699c1b67e809df0976e 100644 --- a/apps/files/l10n/uk.php +++ b/apps/files/l10n/uk.php @@ -26,18 +26,16 @@ $TRANSLATIONS = array( "Share" => "Поділитися", "Delete permanently" => "Видалити назавжди", "Rename" => "Перейменувати", +"Error moving file" => "Помилка переміщення файлу", +"Error" => "Помилка", "Pending" => "Очікування", "Could not rename file" => "Неможливо перейменувати файл", -"replaced {new_name} with {old_name}" => "замінено {new_name} на {old_name}", -"undo" => "відмінити", "_%n folder_::_%n folders_" => array("%n тека","%n тека","%n теки"), "_%n file_::_%n files_" => array("%n файл","%n файлів","%n файли"), "_Uploading %n file_::_Uploading %n files_" => array("","",""), "Your storage is full, files can not be updated or synced anymore!" => "Ваше сховище переповнене, файли більше не можуть бути оновлені або синхронізовані !", "Your storage is almost full ({usedSpacePercent}%)" => "Ваше сховище майже повне ({usedSpacePercent}%)", "Your download is being prepared. This might take some time if the files are big." => "Ваше завантаження готується. Це може зайняти деякий час, якщо файли завеликі.", -"Error moving file" => "Помилка переміщення файлу", -"Error" => "Помилка", "Name" => "Ім'я", "Size" => "Розмір", "Modified" => "Змінено", diff --git a/apps/files/l10n/ur_PK.php b/apps/files/l10n/ur_PK.php index 3e13a7f516d5339043a5ec74c523a73506def9d6..b9548acde92c17a83f69260c7f9bf7f50dc1cba1 100644 --- a/apps/files/l10n/ur_PK.php +++ b/apps/files/l10n/ur_PK.php @@ -1,8 +1,8 @@ "ایرر", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), -"_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "ایرر" +"_Uploading %n file_::_Uploading %n files_" => array("","") ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/vi.php b/apps/files/l10n/vi.php index 8812bb1b209a49cd649822074b5264a95effea88..55f9bd259423f39c3914c891b428dc03e45e636b 100644 --- a/apps/files/l10n/vi.php +++ b/apps/files/l10n/vi.php @@ -37,10 +37,10 @@ $TRANSLATIONS = array( "Share" => "Chia sẻ", "Delete permanently" => "Xóa vĩnh vễn", "Rename" => "Sửa tên", +"Error moving file" => "Lỗi di chuyển tập tin", +"Error" => "Lỗi", "Pending" => "Đang chờ", "Could not rename file" => "Không thể đổi tên file", -"replaced {new_name} with {old_name}" => "đã thay thế {new_name} bằng {old_name}", -"undo" => "lùi lại", "Error deleting file." => "Lỗi xóa file,", "_%n folder_::_%n folders_" => array("%n thư mục"), "_%n file_::_%n files_" => array("%n tập tin"), @@ -51,8 +51,6 @@ $TRANSLATIONS = array( "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Ứng dụng mã hóa đã được kích hoạt nhưng bạn chưa khởi tạo khóa. Vui lòng đăng xuất ra và đăng nhập lại", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Mã hóa đã bị vô hiệu nhưng những tập tin của bạn vẫn được mã hóa. Vui lòng vào phần thiết lập cá nhân để giải mã chúng.", "Your download is being prepared. This might take some time if the files are big." => "Your download is being prepared. This might take some time if the files are big.", -"Error moving file" => "Lỗi di chuyển tập tin", -"Error" => "Lỗi", "Name" => "Tên", "Size" => "Kích cỡ", "Modified" => "Thay đổi", diff --git a/apps/files/l10n/zh_CN.php b/apps/files/l10n/zh_CN.php index 87f8138697e41fd5b6d7632b7bafab8472f70c40..068f97c1ddfb95611ee2bc9f178621059007a373 100644 --- a/apps/files/l10n/zh_CN.php +++ b/apps/files/l10n/zh_CN.php @@ -39,10 +39,10 @@ $TRANSLATIONS = array( "Share" => "分享", "Delete permanently" => "永久删除", "Rename" => "重命名", +"Error moving file" => "移动文件错误", +"Error" => "错误", "Pending" => "等待", "Could not rename file" => "不能重命名文件", -"replaced {new_name} with {old_name}" => "已将 {old_name}替换成 {new_name}", -"undo" => "撤销", "Error deleting file." => "删除文件出错。", "_%n folder_::_%n folders_" => array("%n 文件夹"), "_%n file_::_%n files_" => array("%n个文件"), @@ -54,8 +54,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "无效的私有密钥。请到您的个人配置里去更新私有密钥,来恢复对加密文件的访问。", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "加密是被禁用的,但是您的文件还是被加密了。请到您的个人配置里设置文件加密选项。", "Your download is being prepared. This might take some time if the files are big." => "下载正在准备中。如果文件较大可能会花费一些时间。", -"Error moving file" => "移动文件错误", -"Error" => "错误", "Name" => "名称", "Size" => "大小", "Modified" => "修改日期", diff --git a/apps/files/l10n/zh_HK.php b/apps/files/l10n/zh_HK.php index 4885500ce43b035c3a52369756bfeb5824425462..eaa32cd537a5d00d8a9be7e3125c10fe9d23fe63 100644 --- a/apps/files/l10n/zh_HK.php +++ b/apps/files/l10n/zh_HK.php @@ -2,10 +2,10 @@ $TRANSLATIONS = array( "Files" => "文件", "Share" => "分享", +"Error" => "錯誤", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), -"Error" => "錯誤", "Name" => "名稱", "Upload" => "上傳", "Save" => "儲存", diff --git a/apps/files/l10n/zh_TW.php b/apps/files/l10n/zh_TW.php index caf8b184a3593dc417dc3d144f15dd0cba08d91e..154efd563fddb83f665dc256c2814671579c2bb5 100644 --- a/apps/files/l10n/zh_TW.php +++ b/apps/files/l10n/zh_TW.php @@ -37,10 +37,10 @@ $TRANSLATIONS = array( "Share" => "分享", "Delete permanently" => "永久刪除", "Rename" => "重新命名", +"Error moving file" => "移動檔案失敗", +"Error" => "錯誤", "Pending" => "等候中", "Could not rename file" => "無法重新命名", -"replaced {new_name} with {old_name}" => "使用 {new_name} 取代 {old_name}", -"undo" => "復原", "_%n folder_::_%n folders_" => array("%n 個資料夾"), "_%n file_::_%n files_" => array("%n 個檔案"), "{dirs} and {files}" => "{dirs} 和 {files}", @@ -51,8 +51,6 @@ $TRANSLATIONS = array( "Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "無效的檔案加密私鑰,請在個人設定中更新您的私鑰密語以存取加密的檔案。", "Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "加密已經被停用,但是您的舊檔案還是處於已加密的狀態,請前往個人設定以解密這些檔案。", "Your download is being prepared. This might take some time if the files are big." => "正在準備您的下載,若您的檔案較大,將會需要更多時間。", -"Error moving file" => "移動檔案失敗", -"Error" => "錯誤", "Name" => "名稱", "Size" => "大小", "Modified" => "修改時間", diff --git a/apps/files/lib/app.php b/apps/files/lib/app.php index fea88faa92a872cb17b8757b8d2e952004f246f7..adfca669577babcb6c3afba4067a250835453d67 100644 --- a/apps/files/lib/app.php +++ b/apps/files/lib/app.php @@ -84,25 +84,7 @@ class App { ) { // successful rename $meta = $this->view->getFileInfo($dir . '/' . $newname); - if ($meta['mimetype'] === 'httpd/unix-directory') { - $meta['type'] = 'dir'; - } - else { - $meta['type'] = 'file'; - } - // these need to be set for determineIcon() - $meta['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($meta['mimetype']); - $meta['directory'] = $dir; - $fileinfo = array( - 'id' => $meta['fileid'], - 'mime' => $meta['mimetype'], - 'size' => $meta['size'], - 'etag' => $meta['etag'], - 'directory' => $meta['directory'], - 'name' => $newname, - 'isPreviewAvailable' => $meta['isPreviewAvailable'], - 'icon' => \OCA\Files\Helper::determineIcon($meta) - ); + $fileinfo = \OCA\Files\Helper::formatFileInfo($meta); $result['success'] = true; $result['data'] = $fileinfo; } else { diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index c41e2d155813fd1b3f6333b36566c14c47c55042..b765fdaf3e3ac234653b688bb2a6a516412a49ec 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -19,11 +19,17 @@ class Helper 'usedSpacePercent' => (int)$storageInfo['relative']); } + /** + * Determine icon for a given file + * + * @param \OC\Files\FileInfo $file file info + * @return string icon URL + */ public static function determineIcon($file) { if($file['type'] === 'dir') { $dir = $file['directory']; $icon = \OC_Helper::mimetypeIcon('dir'); - $absPath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir.'/'.$file['name']); + $absPath = $file->getPath(); $mount = \OC\Files\Filesystem::getMountManager()->find($absPath); if (!is_null($mount)) { $sid = $mount->getStorageId(); @@ -38,11 +44,7 @@ class Helper } } }else{ - if($file['isPreviewAvailable']) { - $pathForPreview = $file['directory'] . '/' . $file['name']; - return \OC_Helper::previewIcon($pathForPreview) . '&c=' . $file['etag']; - } - $icon = \OC_Helper::mimetypeIcon($file['mimetype']); + $icon = \OC_Helper::mimetypeIcon($file->getMimetype()); } return substr($icon, 0, -3) . 'svg'; @@ -69,52 +71,58 @@ class Helper } /** - * Retrieves the contents of the given directory and - * returns it as a sorted array. - * @param string $dir path to the directory - * @return array of files + * Formats the file info to be returned as JSON to the client. + * + * @param \OCP\Files\FileInfo file info + * @return array formatted file info */ - public static function getFiles($dir) { - $content = \OC\Files\Filesystem::getDirectoryContent($dir); - $files = array(); + public static function formatFileInfo($i) { + $entry = array(); - foreach ($content as $i) { - $i['date'] = \OCP\Util::formatDate($i['mtime']); - if ($i['type'] === 'file') { - $fileinfo = pathinfo($i['name']); - $i['basename'] = $fileinfo['filename']; - if (!empty($fileinfo['extension'])) { - $i['extension'] = '.' . $fileinfo['extension']; - } else { - $i['extension'] = ''; - } - } - $i['directory'] = $dir; - $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($i['mimetype']); - $i['icon'] = \OCA\Files\Helper::determineIcon($i); - $files[] = $i; + $entry['id'] = $i['fileid']; + $entry['date'] = \OCP\Util::formatDate($i['mtime']); + $entry['mtime'] = $i['mtime'] * 1000; + // only pick out the needed attributes + $entry['icon'] = \OCA\Files\Helper::determineIcon($i); + if (\OC::$server->getPreviewManager()->isMimeSupported($i['mimetype'])) { + $entry['isPreviewAvailable'] = true; + } + $entry['name'] = $i['name']; + $entry['permissions'] = $i['permissions']; + $entry['mimetype'] = $i['mimetype']; + $entry['size'] = $i['size']; + $entry['type'] = $i['type']; + $entry['etag'] = $i['etag']; + if (isset($i['displayname_owner'])) { + $entry['shareOwner'] = $i['displayname_owner']; } + return $entry; + } - usort($files, array('\OCA\Files\Helper', 'fileCmp')); + /** + * Format file info for JSON + * @param \OCP\Files\FileInfo[] $fileInfos file infos + */ + public static function formatFileInfos($fileInfos) { + $files = array(); + foreach ($fileInfos as $i) { + $files[] = self::formatFileInfo($i); + } return $files; } /** - * Splits the given path into a breadcrumb structure. - * @param string $dir path to process - * @return array where each entry is a hash of the absolute - * directory path and its name + * Retrieves the contents of the given directory and + * returns it as a sorted array of FileInfo. + * + * @param string $dir path to the directory + * @return \OCP\Files\FileInfo[] files */ - public static function makeBreadcrumb($dir){ - $breadcrumb = array(); - $pathtohere = ''; - foreach (explode('/', $dir) as $i) { - if ($i !== '') { - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); - } - } - return $breadcrumb; + public static function getFiles($dir) { + $content = \OC\Files\Filesystem::getDirectoryContent($dir); + + usort($content, array('\OCA\Files\Helper', 'fileCmp')); + return $content; } } diff --git a/apps/files/templates/admin.php b/apps/files/templates/admin.php index a5afd55fbc3938263c9e745be7281175f9fe123a..5f7d3261d6c1a5dd2e6b16f347a2493f3e072a06 100644 --- a/apps/files/templates/admin.php +++ b/apps/files/templates/admin.php @@ -1,28 +1,26 @@ -
-
-

t('File handling')); ?>

- - - '/> - - (t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>) - -
+ +

t('File handling')); ?>

+ + + '/> + + (t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>) - checked="checked" /> -
+
+ + checked="checked" /> +
- ' - title="t( '0 is unlimited' )); ?>" - disabled="disabled" />
- t( 'Maximum input size for ZIP files' )); ?>
+ ' + title="t( '0 is unlimited' )); ?>" + disabled="disabled" />
+ t( 'Maximum input size for ZIP files' )); ?>
- - -
+ +
diff --git a/apps/files/templates/fileexists.html b/apps/files/templates/fileexists.html index 662177ac7ed79b56ed12360f998b807131e27e2b..79beccef3e507fa5e18962de1d578a8775adfc10 100644 --- a/apps/files/templates/fileexists.html +++ b/apps/files/templates/fileexists.html @@ -3,8 +3,8 @@ {what}

- - + +
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 5b0bad7f3418fabff253ac34a812dcc2d5eb2b43..95edd625cb31491552427f55b79b02d3e9680b02 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -1,19 +1,18 @@
- -
+
-
+
-
class="hidden">t('Nothing in here. Upload something!'))?>
+ - - - + -
class="hidden" id='headerName'> + class="hidden" id="headerSize">t('Size')); ?>class="hidden" id="headerDate"> +
@@ -111,7 +109,6 @@ - diff --git a/apps/files/templates/part.breadcrumb.php b/apps/files/templates/part.breadcrumb.php deleted file mode 100644 index 2a0df6227679307c6840d5cb5fcf839c422c0d24..0000000000000000000000000000000000000000 --- a/apps/files/templates/part.breadcrumb.php +++ /dev/null @@ -1,17 +0,0 @@ -
" data-dir=''> - - - - - -
- -
svg" - data-dir=''> - -
- -160) $relative_date_color = 160; - $name = \OCP\Util::encodePath($file['name']); - $directory = \OCP\Util::encodePath($file['directory']); ?> - - data-share-owner="" - - > - - - - - style="background-image:url()" - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - -viewMock->expects($this->any()) ->method('getFileInfo') - ->will($this->returnValue(array( + ->will($this->returnValue(new \OC\Files\FileInfo( + '/test', + null, + '/test', + array( 'fileid' => 123, 'type' => 'dir', 'mimetype' => 'httpd/unix-directory', + 'mtime' => 0, + 'permissions' => 31, 'size' => 18, 'etag' => 'abcdef', 'directory' => '/', 'name' => 'new_name', - ))); + )))); $result = $this->files->rename($dir, $oldname, $newname); $this->assertTrue($result['success']); $this->assertEquals(123, $result['data']['id']); $this->assertEquals('new_name', $result['data']['name']); - $this->assertEquals('/test', $result['data']['directory']); $this->assertEquals(18, $result['data']['size']); - $this->assertEquals('httpd/unix-directory', $result['data']['mime']); + $this->assertEquals('httpd/unix-directory', $result['data']['mimetype']); $icon = \OC_Helper::mimetypeIcon('dir'); $icon = substr($icon, 0, -3) . 'svg'; $this->assertEquals($icon, $result['data']['icon']); - $this->assertFalse($result['data']['isPreviewAvailable']); } /** @@ -148,29 +152,33 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase { $this->viewMock->expects($this->any()) ->method('getFileInfo') - ->will($this->returnValue(array( + ->will($this->returnValue(new \OC\Files\FileInfo( + '/', + null, + '/', + array( 'fileid' => 123, 'type' => 'dir', 'mimetype' => 'httpd/unix-directory', + 'mtime' => 0, + 'permissions' => 31, 'size' => 18, 'etag' => 'abcdef', 'directory' => '/', 'name' => 'new_name', - ))); + )))); $result = $this->files->rename($dir, $oldname, $newname); $this->assertTrue($result['success']); $this->assertEquals(123, $result['data']['id']); - $this->assertEquals('newname', $result['data']['name']); - $this->assertEquals('/', $result['data']['directory']); + $this->assertEquals('new_name', $result['data']['name']); $this->assertEquals(18, $result['data']['size']); - $this->assertEquals('httpd/unix-directory', $result['data']['mime']); + $this->assertEquals('httpd/unix-directory', $result['data']['mimetype']); $this->assertEquals('abcdef', $result['data']['etag']); $icon = \OC_Helper::mimetypeIcon('dir'); $icon = substr($icon, 0, -3) . 'svg'; $this->assertEquals($icon, $result['data']['icon']); - $this->assertFalse($result['data']['isPreviewAvailable']); } /** diff --git a/apps/files/tests/js/breadcrumbSpec.js b/apps/files/tests/js/breadcrumbSpec.js new file mode 100644 index 0000000000000000000000000000000000000000..1bfe5308a278c0dcabfcff3a9661ec14c01b47fc --- /dev/null +++ b/apps/files/tests/js/breadcrumbSpec.js @@ -0,0 +1,248 @@ +/** +* ownCloud +* +* @author Vincent Petry +* @copyright 2014 Vincent Petry +* +* 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 . +* +*/ + +/* global BreadCrumb */ +describe('BreadCrumb tests', function() { + describe('Rendering', function() { + var bc; + beforeEach(function() { + bc = new BreadCrumb({ + getCrumbUrl: function(part, index) { + // for testing purposes + return part.dir + '#' + index; + } + }); + }); + afterEach(function() { + bc = null; + }); + it('Renders its own container', function() { + bc.render(); + expect(bc.$el.hasClass('breadcrumb')).toEqual(true); + }); + it('Renders root by default', function() { + var $crumbs; + bc.render(); + $crumbs = bc.$el.find('.crumb'); + expect($crumbs.length).toEqual(1); + expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0'); + expect($crumbs.eq(0).find('img').length).toEqual(1); + expect($crumbs.eq(0).attr('data-dir')).toEqual('/'); + }); + it('Renders root when switching to root', function() { + var $crumbs; + bc.setDirectory('/somedir'); + bc.setDirectory('/'); + $crumbs = bc.$el.find('.crumb'); + expect($crumbs.length).toEqual(1); + expect($crumbs.eq(0).attr('data-dir')).toEqual('/'); + }); + it('Renders last crumb with "last" class', function() { + bc.setDirectory('/abc/def'); + expect(bc.$el.find('.crumb:last').hasClass('last')).toEqual(true); + }); + it('Renders single path section', function() { + var $crumbs; + bc.setDirectory('/somedir'); + $crumbs = bc.$el.find('.crumb'); + expect($crumbs.length).toEqual(2); + expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0'); + expect($crumbs.eq(0).find('img').length).toEqual(1); + expect($crumbs.eq(0).attr('data-dir')).toEqual('/'); + expect($crumbs.eq(1).find('a').attr('href')).toEqual('/somedir#1'); + expect($crumbs.eq(1).find('img').length).toEqual(0); + expect($crumbs.eq(1).attr('data-dir')).toEqual('/somedir'); + }); + it('Renders multiple path sections and special chars', function() { + var $crumbs; + bc.setDirectory('/somedir/with space/abc'); + $crumbs = bc.$el.find('.crumb'); + expect($crumbs.length).toEqual(4); + expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0'); + expect($crumbs.eq(0).find('img').length).toEqual(1); + expect($crumbs.eq(0).attr('data-dir')).toEqual('/'); + + expect($crumbs.eq(1).find('a').attr('href')).toEqual('/somedir#1'); + expect($crumbs.eq(1).find('img').length).toEqual(0); + expect($crumbs.eq(1).attr('data-dir')).toEqual('/somedir'); + + expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir/with space#2'); + expect($crumbs.eq(2).find('img').length).toEqual(0); + expect($crumbs.eq(2).attr('data-dir')).toEqual('/somedir/with space'); + + expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with space/abc#3'); + expect($crumbs.eq(3).find('img').length).toEqual(0); + expect($crumbs.eq(3).attr('data-dir')).toEqual('/somedir/with space/abc'); + }); + }); + describe('Events', function() { + it('Calls onClick handler when clicking on a crumb', function() { + var handler = sinon.stub(); + var bc = new BreadCrumb({ + onClick: handler + }); + bc.setDirectory('/one/two/three/four'); + bc.$el.find('.crumb:eq(3)').click(); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).thisValue).toEqual(bc.$el.find('.crumb').get(3)); + + handler.reset(); + bc.$el.find('.crumb:eq(0) a').click(); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).thisValue).toEqual(bc.$el.find('.crumb').get(0)); + }); + it('Calls onDrop handler when dropping on a crumb', function() { + var droppableStub = sinon.stub($.fn, 'droppable'); + var handler = sinon.stub(); + var bc = new BreadCrumb({ + onDrop: handler + }); + bc.setDirectory('/one/two/three/four'); + expect(droppableStub.calledOnce).toEqual(true); + + expect(droppableStub.getCall(0).args[0].drop).toBeDefined(); + // simulate drop + droppableStub.getCall(0).args[0].drop({dummy: true}); + + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0]).toEqual({dummy: true}); + + droppableStub.restore(); + }); + }); + describe('Resizing', function() { + var bc, widthStub, dummyDir, + oldUpdateTotalWidth; + + beforeEach(function() { + dummyDir = '/short name/longer name/looooooooooooonger/even longer long long long longer long/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/last one'; + + oldUpdateTotalWidth = BreadCrumb.prototype._updateTotalWidth; + BreadCrumb.prototype._updateTotalWidth = function() { + // need to set display:block for correct offsetWidth (no CSS loaded here) + $('div.crumb').css({ + 'display': 'block', + 'float': 'left' + }); + + return oldUpdateTotalWidth.apply(this, arguments); + }; + + bc = new BreadCrumb(); + widthStub = sinon.stub($.fn, 'width'); + // append dummy navigation and controls + // as they are currently used for measurements + $('#testArea').append( + '', + '
' + ); + + // make sure we know the test screen width + $('#testArea').css('width', 1280); + + // use test area as we need it for measurements + $('#controls').append(bc.$el); + $('#controls').append('
Dummy action with a given width
'); + }); + afterEach(function() { + BreadCrumb.prototype._updateTotalWidth = oldUpdateTotalWidth; + widthStub.restore(); + bc = null; + }); + it('Hides breadcrumbs to fit window', function() { + var $crumbs; + + widthStub.returns(500); + // triggers resize implicitly + bc.setDirectory(dummyDir); + $crumbs = bc.$el.find('.crumb'); + + // first one is always visible + expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); + // second one has ellipsis + expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); + expect($crumbs.eq(1).find('.ellipsis').length).toEqual(1); + // there is only one ellipsis in total + expect($crumbs.find('.ellipsis').length).toEqual(1); + // subsequent elements are hidden + expect($crumbs.eq(2).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); + }); + it('Updates ellipsis on window size increase', function() { + var $crumbs; + + widthStub.returns(500); + // triggers resize implicitly + bc.setDirectory(dummyDir); + $crumbs = bc.$el.find('.crumb'); + + // simulate increase + $('#testArea').css('width', 1800); + bc.resize(1800); + + // first one is always visible + expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); + // second one has ellipsis + expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); + expect($crumbs.eq(1).find('.ellipsis').length).toEqual(1); + // there is only one ellipsis in total + expect($crumbs.find('.ellipsis').length).toEqual(1); + // subsequent elements are hidden + expect($crumbs.eq(2).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); + // the rest is visible + expect($crumbs.eq(5).hasClass('hidden')).toEqual(false); + expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); + }); + it('Updates ellipsis on window size decrease', function() { + var $crumbs; + + $('#testArea').css('width', 2000); + widthStub.returns(2000); + // triggers resize implicitly + bc.setDirectory(dummyDir); + $crumbs = bc.$el.find('.crumb'); + + // simulate decrease + bc.resize(500); + $('#testArea').css('width', 500); + + // first one is always visible + expect($crumbs.eq(0).hasClass('hidden')).toEqual(false); + // second one has ellipsis + expect($crumbs.eq(1).hasClass('hidden')).toEqual(false); + expect($crumbs.eq(1).find('.ellipsis').length).toEqual(1); + // there is only one ellipsis in total + expect($crumbs.find('.ellipsis').length).toEqual(1); + // subsequent elements are hidden + expect($crumbs.eq(2).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(3).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(4).hasClass('hidden')).toEqual(true); + // the rest is visible + expect($crumbs.eq(5).hasClass('hidden')).toEqual(true); + expect($crumbs.eq(6).hasClass('hidden')).toEqual(false); + }); + }); +}); diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index ef7ddcb874ab143c5901bb4e236e52ca4ec4ab0b..3c22c84b866d979397eaaac831a402dbd72149be 100644 --- a/apps/files/tests/js/fileactionsSpec.js +++ b/apps/files/tests/js/fileactionsSpec.js @@ -22,6 +22,7 @@ /* global OC, FileActions, FileList */ describe('FileActions tests', function() { var $filesTable; + beforeEach(function() { // init horrible parameters var $body = $('body'); @@ -34,42 +35,83 @@ describe('FileActions tests', function() { $('#dir, #permissions, #filestable').remove(); }); it('calling display() sets file actions', function() { - // note: download_url is actually the link target, not the actual download URL... - var $tr = FileList.addFile('testName.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'}); - - // no actions before call - expect($tr.find('.action[data-action=Download]').length).toEqual(0); - expect($tr.find('.action[data-action=Rename]').length).toEqual(0); - expect($tr.find('.action.delete').length).toEqual(0); + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'plain/text', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; - FileActions.display($tr.find('td.filename'), true); + // note: FileActions.display() is called implicitly + var $tr = FileList.add(fileData); - // actions defined after cal - expect($tr.find('.action[data-action=Download]').length).toEqual(1); - expect($tr.find('.nametext .action[data-action=Rename]').length).toEqual(1); + // actions defined after call + expect($tr.find('.action.action-download').length).toEqual(1); + expect($tr.find('.action.action-download').attr('data-action')).toEqual('Download'); + expect($tr.find('.nametext .action.action-rename').length).toEqual(1); + expect($tr.find('.nametext .action.action-rename').attr('data-action')).toEqual('Rename'); expect($tr.find('.action.delete').length).toEqual(1); }); it('calling display() twice correctly replaces file actions', function() { - var $tr = FileList.addFile('testName.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'}); + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'plain/text', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; + var $tr = FileList.add(fileData); FileActions.display($tr.find('td.filename'), true); FileActions.display($tr.find('td.filename'), true); // actions defined after cal - expect($tr.find('.action[data-action=Download]').length).toEqual(1); - expect($tr.find('.nametext .action[data-action=Rename]').length).toEqual(1); + expect($tr.find('.action.action-download').length).toEqual(1); + expect($tr.find('.nametext .action.action-rename').length).toEqual(1); expect($tr.find('.action.delete').length).toEqual(1); }); it('redirects to download URL when clicking download', function() { var redirectStub = sinon.stub(OC, 'redirect'); - // note: download_url is actually the link target, not the actual download URL... - var $tr = FileList.addFile('test download File.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'}); + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'plain/text', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; + var $tr = FileList.add(fileData); FileActions.display($tr.find('td.filename'), true); - $tr.find('.action[data-action=Download]').click(); + $tr.find('.action-download').click(); expect(redirectStub.calledOnce).toEqual(true); - expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20download%20File.txt'); + expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=testName.txt'); redirectStub.restore(); }); + it('deletes file when clicking delete', function() { + var deleteStub = sinon.stub(FileList, 'do_delete'); + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'plain/text', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; + var $tr = FileList.add(fileData); + FileActions.display($tr.find('td.filename'), true); + + $tr.find('.action.delete').click(); + + expect(deleteStub.calledOnce).toEqual(true); + deleteStub.restore(); + }); }); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 8f4cb86ab4ae14158b737a6e4a761866a4fb6eda..ca85a360cf508a0e684b17e123b76fa7da7039de 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -21,6 +21,9 @@ /* global OC, FileList */ describe('FileList tests', function() { + var testFiles, alertStub, notificationStub, + pushStateStub; + beforeEach(function() { // init horrible parameters var $body = $('body'); @@ -28,45 +31,784 @@ describe('FileList tests', function() { $body.append(''); // dummy files table $body.append('
'); + + // prevents URL changes during tests + pushStateStub = sinon.stub(window.history, 'pushState'); + + alertStub = sinon.stub(OC.dialogs, 'alert'); + notificationStub = sinon.stub(OC.Notification, 'show'); + + // init parameters and test table elements + $('#testArea').append( + '' + + '' + + // dummy controls + '
' + + '
' + + '
' + + '
' + + // dummy table + '' + + '' + + '' + + '
' + + '
Empty content message
' + ); + + testFiles = [{ + id: 1, + type: 'file', + name: 'One.txt', + mimetype: 'text/plain', + size: 12 + }, { + id: 2, + type: 'file', + name: 'Two.jpg', + mimetype: 'image/jpeg', + size: 12049 + }, { + id: 3, + type: 'file', + name: 'Three.pdf', + mimetype: 'application/pdf', + size: 58009 + }, { + id: 4, + type: 'dir', + name: 'somedir', + mimetype: 'httpd/unix-directory', + size: 250 + }]; + + FileList.initialize(); }); afterEach(function() { + testFiles = undefined; + FileList.initialized = false; + FileList.isEmpty = true; + delete FileList._reloadCall; + $('#dir, #permissions, #filestable').remove(); + notificationStub.restore(); + alertStub.restore(); + pushStateStub.restore(); + }); + describe('Getters', function() { + it('Returns the current directory', function() { + $('#dir').val('/one/two/three'); + expect(FileList.getCurrentDirectory()).toEqual('/one/two/three'); + }); + it('Returns the directory permissions as int', function() { + $('#permissions').val('23'); + expect(FileList.getDirectoryPermissions()).toEqual(23); + }); + }); + describe('Adding files', function() { + var clock, now; + beforeEach(function() { + // to prevent date comparison issues + clock = sinon.useFakeTimers(); + now = new Date(); + }); + afterEach(function() { + clock.restore(); + }); + it('generates file element with correct attributes when calling add() with file data', function() { + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'plain/text', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; + var $tr = FileList.add(fileData); + + expect($tr).toBeDefined(); + expect($tr[0].tagName.toLowerCase()).toEqual('tr'); + expect($tr.attr('data-id')).toEqual('18'); + expect($tr.attr('data-type')).toEqual('file'); + expect($tr.attr('data-file')).toEqual('testName.txt'); + expect($tr.attr('data-size')).toEqual('1234'); + expect($tr.attr('data-etag')).toEqual('a01234c'); + expect($tr.attr('data-permissions')).toEqual('31'); + expect($tr.attr('data-mime')).toEqual('plain/text'); + expect($tr.attr('data-mtime')).toEqual('123456'); + expect($tr.find('a.name').attr('href')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=testName.txt'); + + expect($tr.find('.filesize').text()).toEqual('1 kB'); + expect(FileList.findFileEl('testName.txt')[0]).toEqual($tr[0]); + }); + it('generates dir element with correct attributes when calling add() with dir data', function() { + var fileData = { + id: 19, + type: 'dir', + name: 'testFolder', + mimetype: 'httpd/unix-directory', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; + var $tr = FileList.add(fileData); + + expect($tr).toBeDefined(); + expect($tr[0].tagName.toLowerCase()).toEqual('tr'); + expect($tr.attr('data-id')).toEqual('19'); + expect($tr.attr('data-type')).toEqual('dir'); + expect($tr.attr('data-file')).toEqual('testFolder'); + expect($tr.attr('data-size')).toEqual('1234'); + expect($tr.attr('data-etag')).toEqual('a01234c'); + expect($tr.attr('data-permissions')).toEqual('31'); + expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); + expect($tr.attr('data-mtime')).toEqual('123456'); + + expect($tr.find('.filesize').text()).toEqual('1 kB'); + + expect(FileList.findFileEl('testFolder')[0]).toEqual($tr[0]); + }); + it('generates file element with default attributes when calling add() with minimal data', function() { + var fileData = { + type: 'file', + name: 'testFile.txt' + }; + + clock.tick(123456); + var $tr = FileList.add(fileData); + + expect($tr).toBeDefined(); + expect($tr[0].tagName.toLowerCase()).toEqual('tr'); + expect($tr.attr('data-id')).toEqual(null); + expect($tr.attr('data-type')).toEqual('file'); + expect($tr.attr('data-file')).toEqual('testFile.txt'); + expect($tr.attr('data-size')).toEqual(null); + expect($tr.attr('data-etag')).toEqual(null); + expect($tr.attr('data-permissions')).toEqual('31'); + expect($tr.attr('data-mime')).toEqual(null); + expect($tr.attr('data-mtime')).toEqual('123456'); + + expect($tr.find('.filesize').text()).toEqual('Pending'); + }); + it('generates dir element with default attributes when calling add() with minimal data', function() { + var fileData = { + type: 'dir', + name: 'testFolder' + }; + clock.tick(123456); + var $tr = FileList.add(fileData); + + expect($tr).toBeDefined(); + expect($tr[0].tagName.toLowerCase()).toEqual('tr'); + expect($tr.attr('data-id')).toEqual(null); + expect($tr.attr('data-type')).toEqual('dir'); + expect($tr.attr('data-file')).toEqual('testFolder'); + expect($tr.attr('data-size')).toEqual(null); + expect($tr.attr('data-etag')).toEqual(null); + expect($tr.attr('data-permissions')).toEqual('31'); + expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); + expect($tr.attr('data-mtime')).toEqual('123456'); + + expect($tr.find('.filesize').text()).toEqual('Pending'); + }); + it('generates file element with zero size when size is explicitly zero', function() { + var fileData = { + type: 'dir', + name: 'testFolder', + size: '0' + }; + var $tr = FileList.add(fileData); + expect($tr.find('.filesize').text()).toEqual('0 B'); + }); + it('adds new file to the end of the list before the summary', function() { + var fileData = { + type: 'file', + name: 'P comes after O.txt' + }; + FileList.setFiles(testFiles); + $tr = FileList.add(fileData); + expect($tr.index()).toEqual(4); + expect($tr.next().hasClass('summary')).toEqual(true); + }); + it('adds new file at correct position in insert mode', function() { + var fileData = { + type: 'file', + name: 'P comes after O.txt' + }; + FileList.setFiles(testFiles); + $tr = FileList.add(fileData, {insert: true}); + // after "One.txt" + expect($tr.index()).toEqual(1); + }); + it('removes empty content message and shows summary when adding first file', function() { + var fileData = { + type: 'file', + name: 'first file.txt', + size: 12 + }; + FileList.setFiles([]); + expect(FileList.isEmpty).toEqual(true); + FileList.add(fileData); + $summary = $('#fileList .summary'); + expect($summary.length).toEqual(1); + // yes, ugly... + expect($summary.find('.info').text()).toEqual('0 folders and 1 file'); + expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true); + expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false); + expect($summary.find('.filesize').text()).toEqual('12 B'); + expect($('#filestable thead th').hasClass('hidden')).toEqual(false); + expect($('#emptycontent').hasClass('hidden')).toEqual(true); + expect(FileList.isEmpty).toEqual(false); + }); }); - it('generates file element with correct attributes when calling addFile', function() { - var lastMod = new Date(10000); - // note: download_url is actually the link target, not the actual download URL... - var $tr = FileList.addFile('testName.txt', 1234, lastMod, false, false, {download_url: 'test/download/url'}); - - expect($tr).toBeDefined(); - expect($tr[0].tagName.toLowerCase()).toEqual('tr'); - expect($tr.find('a:first').attr('href')).toEqual('test/download/url'); - expect($tr.attr('data-type')).toEqual('file'); - expect($tr.attr('data-file')).toEqual('testName.txt'); - expect($tr.attr('data-size')).toEqual('1234'); - expect($tr.attr('data-permissions')).toEqual('31'); - //expect($tr.attr('data-mime')).toEqual('plain/text'); + describe('Removing files from the list', function() { + it('Removes file from list when calling remove() and updates summary', function() { + var $removedEl; + FileList.setFiles(testFiles); + $removedEl = FileList.remove('One.txt'); + expect($removedEl).toBeDefined(); + expect($removedEl.attr('data-file')).toEqual('One.txt'); + expect($('#fileList tr:not(.summary)').length).toEqual(3); + expect(FileList.findFileEl('One.txt').length).toEqual(0); + + $summary = $('#fileList .summary'); + expect($summary.length).toEqual(1); + expect($summary.find('.info').text()).toEqual('1 folder and 2 files'); + expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(false); + expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false); + expect($summary.find('.filesize').text()).toEqual('69 kB'); + expect(FileList.isEmpty).toEqual(false); + }); + it('Shows empty content when removing last file', function() { + FileList.setFiles([testFiles[0]]); + FileList.remove('One.txt'); + expect($('#fileList tr:not(.summary)').length).toEqual(0); + expect(FileList.findFileEl('One.txt').length).toEqual(0); + + $summary = $('#fileList .summary'); + expect($summary.length).toEqual(0); + expect($('#filestable thead th').hasClass('hidden')).toEqual(true); + expect($('#emptycontent').hasClass('hidden')).toEqual(false); + expect(FileList.isEmpty).toEqual(true); + }); }); - it('generates dir element with correct attributes when calling addDir', function() { - var lastMod = new Date(10000); - var $tr = FileList.addDir('testFolder', 1234, lastMod, false); - - expect($tr).toBeDefined(); - expect($tr[0].tagName.toLowerCase()).toEqual('tr'); - expect($tr.attr('data-type')).toEqual('dir'); - expect($tr.attr('data-file')).toEqual('testFolder'); - expect($tr.attr('data-size')).toEqual('1234'); - expect($tr.attr('data-permissions')).toEqual('31'); - //expect($tr.attr('data-mime')).toEqual('httpd/unix-directory'); + describe('Deleting files', function() { + function doDelete() { + var request, query; + // note: normally called from FileActions + FileList.do_delete(['One.txt', 'Two.jpg']); + + expect(fakeServer.requests.length).toEqual(1); + request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php'); + + query = fakeServer.requests[0].requestBody; + expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir', files: '["One.txt","Two.jpg"]'}); + } + it('calls delete.php, removes the deleted entries and updates summary', function() { + FileList.setFiles(testFiles); + doDelete(); + + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + expect(FileList.findFileEl('One.txt').length).toEqual(0); + expect(FileList.findFileEl('Two.jpg').length).toEqual(0); + expect(FileList.findFileEl('Three.pdf').length).toEqual(1); + expect(FileList.$fileList.find('tr:not(.summary)').length).toEqual(2); + + $summary = $('#fileList .summary'); + expect($summary.length).toEqual(1); + expect($summary.find('.info').text()).toEqual('1 folder and 1 file'); + expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(false); + expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false); + expect($summary.find('.filesize').text()).toEqual('57 kB'); + expect(FileList.isEmpty).toEqual(false); + expect($('#filestable thead th').hasClass('hidden')).toEqual(false); + expect($('#emptycontent').hasClass('hidden')).toEqual(true); + + expect(notificationStub.notCalled).toEqual(true); + }); + it('updates summary when deleting last file', function() { + FileList.setFiles([testFiles[0], testFiles[1]]); + doDelete(); + + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + + expect(FileList.$fileList.find('tr:not(.summary)').length).toEqual(0); + + $summary = $('#fileList .summary'); + expect($summary.length).toEqual(0); + expect(FileList.isEmpty).toEqual(true); + expect($('#filestable thead th').hasClass('hidden')).toEqual(true); + expect($('#emptycontent').hasClass('hidden')).toEqual(false); + }); + it('bring back deleted item when delete call failed', function() { + FileList.setFiles(testFiles); + doDelete(); + + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'error', data: {message: 'WOOT'}}) + ); + + // files are still in the list + expect(FileList.findFileEl('One.txt').length).toEqual(1); + expect(FileList.findFileEl('Two.jpg').length).toEqual(1); + expect(FileList.$fileList.find('tr:not(.summary)').length).toEqual(4); + + expect(notificationStub.calledOnce).toEqual(true); + }); + }); + describe('Renaming files', function() { + function doRename() { + var $input, request; + + FileList.setFiles(testFiles); + + // trigger rename prompt + FileList.rename('One.txt'); + $input = FileList.$fileList.find('input.filename'); + $input.val('One_renamed.txt').blur(); + + expect(fakeServer.requests.length).toEqual(1); + var request = fakeServer.requests[0]; + expect(request.url.substr(0, request.url.indexOf('?'))).toEqual(OC.webroot + '/index.php/apps/files/ajax/rename.php'); + expect(OC.parseQueryString(request.url)).toEqual({'dir': '/subdir', newname: 'One_renamed.txt', file: 'One.txt'}); + + // element is renamed before the request finishes + expect(FileList.findFileEl('One.txt').length).toEqual(0); + expect(FileList.findFileEl('One_renamed.txt').length).toEqual(1); + // input is gone + expect(FileList.$fileList.find('input.filename').length).toEqual(0); + } + it('Keeps renamed file entry if rename ajax call suceeded', function() { + doRename(); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'One_renamed.txt' + } + })); + + // element stays renamed + expect(FileList.findFileEl('One.txt').length).toEqual(0); + expect(FileList.findFileEl('One_renamed.txt').length).toEqual(1); + + expect(alertStub.notCalled).toEqual(true); + }); + it('Reverts file entry if rename ajax call failed', function() { + doRename(); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'error', + data: { + message: 'Something went wrong' + } + })); + + // element was reverted + expect(FileList.findFileEl('One.txt').length).toEqual(1); + expect(FileList.findFileEl('One_renamed.txt').length).toEqual(0); + + expect(alertStub.calledOnce).toEqual(true); + }); + it('Correctly updates file link after rename', function() { + var $tr; + doRename(); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'One_renamed.txt' + } + })); + + $tr = FileList.findFileEl('One_renamed.txt'); + expect($tr.find('a.name').attr('href')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=One_renamed.txt'); + }); + // FIXME: fix this in the source code! + xit('Correctly updates file link after rename when path has same name', function() { + var $tr; + // evil case: because of buggy code + $('#dir').val('/One.txt/subdir'); + doRename(); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'One_renamed.txt' + } + })); + + $tr = FileList.findFileEl('One_renamed.txt'); + expect($tr.find('a.name').attr('href')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=One.txt'); + }); + }); + describe('List rendering', function() { + it('renders a list of files using add()', function() { + var addSpy = sinon.spy(FileList, 'add'); + FileList.setFiles(testFiles); + expect(addSpy.callCount).toEqual(4); + expect($('#fileList tr:not(.summary)').length).toEqual(4); + addSpy.restore(); + }); + it('updates summary using the file sizes', function() { + var $summary; + FileList.setFiles(testFiles); + $summary = $('#fileList .summary'); + expect($summary.length).toEqual(1); + expect($summary.find('.info').text()).toEqual('1 folder and 3 files'); + expect($summary.find('.filesize').text()).toEqual('69 kB'); + }); + it('shows headers, summary and hide empty content message after setting files', function(){ + FileList.setFiles(testFiles); + expect($('#filestable thead th').hasClass('hidden')).toEqual(false); + expect($('#emptycontent').hasClass('hidden')).toEqual(true); + expect(FileList.$fileList.find('.summary').length).toEqual(1); + }); + it('hides headers, summary and show empty content message after setting empty file list', function(){ + FileList.setFiles([]); + expect($('#filestable thead th').hasClass('hidden')).toEqual(true); + expect($('#emptycontent').hasClass('hidden')).toEqual(false); + expect(FileList.$fileList.find('.summary').length).toEqual(0); + }); + it('hides headers, empty content message, and summary when list is empty and user has no creation permission', function(){ + $('#permissions').val(0); + FileList.setFiles([]); + expect($('#filestable thead th').hasClass('hidden')).toEqual(true); + expect($('#emptycontent').hasClass('hidden')).toEqual(true); + expect(FileList.$fileList.find('.summary').length).toEqual(0); + }); + it('calling findFileEl() can find existing file element', function() { + FileList.setFiles(testFiles); + expect(FileList.findFileEl('Two.jpg').length).toEqual(1); + }); + it('calling findFileEl() returns empty when file not found in file', function() { + FileList.setFiles(testFiles); + expect(FileList.findFileEl('unexist.dat').length).toEqual(0); + }); + it('only add file if in same current directory', function() { + $('#dir').val('/current dir'); + var fileData = { + type: 'file', + name: 'testFile.txt', + directory: '/current dir' + }; + var $tr = FileList.add(fileData); + expect(FileList.findFileEl('testFile.txt').length).toEqual(1); + }); + it('triggers "fileActionsReady" event after update', function() { + var handler = sinon.stub(); + FileList.$fileList.on('fileActionsReady', handler); + FileList.setFiles(testFiles); + expect(handler.calledOnce).toEqual(true); + }); + it('triggers "updated" event after update', function() { + var handler = sinon.stub(); + FileList.$fileList.on('updated', handler); + FileList.setFiles(testFiles); + expect(handler.calledOnce).toEqual(true); + }); + }); + describe('file previews', function() { + var previewLoadStub; + + function getImageUrl($el) { + // might be slightly different cross-browser + var url = $el.css('background-image'); + var r = url.match(/url\(['"]?([^'")]*)['"]?\)/); + if (!r) { + return url; + } + return r[1]; + } + + beforeEach(function() { + previewLoadStub = sinon.stub(Files, 'lazyLoadPreview'); + }); + afterEach(function() { + previewLoadStub.restore(); + }); + it('renders default icon for file when none provided and no preview is available', function() { + var fileData = { + type: 'file', + name: 'testFile.txt' + }; + var $tr = FileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + }); + it('renders default icon for dir when none provided and no preview is available', function() { + var fileData = { + type: 'dir', + name: 'test dir' + }; + var $tr = FileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/folder.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + }); + it('renders provided icon for file when provided', function() { + var fileData = { + type: 'file', + name: 'test dir', + icon: OC.webroot + '/core/img/filetypes/application-pdf.svg' + }; + var $tr = FileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/application-pdf.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + }); + it('renders preview when no icon was provided and preview is available', function() { + var fileData = { + type: 'file', + name: 'test dir', + isPreviewAvailable: true + }; + var $tr = FileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + expect(previewLoadStub.calledOnce).toEqual(true); + // third argument is callback + previewLoadStub.getCall(0).args[2](OC.webroot + '/somepath.png'); + expect(getImageUrl($td)).toEqual(OC.webroot + '/somepath.png'); + }); + it('renders default file type icon when no icon was provided and no preview is available', function() { + var fileData = { + type: 'file', + name: 'test dir', + isPreviewAvailable: false + }; + var $tr = FileList.add(fileData); + var $td = $tr.find('td.filename'); + expect(getImageUrl($td)).toEqual(OC.webroot + '/core/img/filetypes/file.svg'); + expect(previewLoadStub.notCalled).toEqual(true); + }); + }); + describe('viewer mode', function() { + it('enabling viewer mode hides files table and action buttons', function() { + FileList.setViewerMode(true); + expect($('#filestable').hasClass('hidden')).toEqual(true); + expect($('.actions').hasClass('hidden')).toEqual(true); + expect($('.notCreatable').hasClass('hidden')).toEqual(true); + }); + it('disabling viewer mode restores files table and action buttons', function() { + FileList.setViewerMode(true); + FileList.setViewerMode(false); + expect($('#filestable').hasClass('hidden')).toEqual(false); + expect($('.actions').hasClass('hidden')).toEqual(false); + expect($('.notCreatable').hasClass('hidden')).toEqual(true); + }); + it('disabling viewer mode restores files table and action buttons with correct permissions', function() { + $('#permissions').val(0); + FileList.setViewerMode(true); + FileList.setViewerMode(false); + expect($('#filestable').hasClass('hidden')).toEqual(false); + expect($('.actions').hasClass('hidden')).toEqual(true); + expect($('.notCreatable').hasClass('hidden')).toEqual(false); + }); + }); + describe('loading file list', function() { + beforeEach(function() { + var data = { + status: 'success', + data: { + files: testFiles, + permissions: 31 + } + }; + fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2F(subdir|anothersubdir)/, [ + 200, { + "Content-Type": "application/json" + }, + JSON.stringify(data) + ]); + }); + it('fetches file list from server and renders it when reload() is called', function() { + FileList.reload(); + expect(fakeServer.requests.length).toEqual(1); + var url = fakeServer.requests[0].url; + var query = url.substr(url.indexOf('?') + 1); + expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir'}); + fakeServer.respond(); + expect($('#fileList tr:not(.summary)').length).toEqual(4); + expect(FileList.findFileEl('One.txt').length).toEqual(1); + }); + it('switches dir and fetches file list when calling changeDirectory()', function() { + FileList.changeDirectory('/anothersubdir'); + expect(FileList.getCurrentDirectory()).toEqual('/anothersubdir'); + expect(fakeServer.requests.length).toEqual(1); + var url = fakeServer.requests[0].url; + var query = url.substr(url.indexOf('?') + 1); + expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir'}); + fakeServer.respond(); + }); + it('switches to root dir when current directory does not exist', function() { + fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2funexist/, [ + 404, { + "Content-Type": "application/json" + }, + '' + ]); + FileList.changeDirectory('/unexist'); + fakeServer.respond(); + expect(FileList.getCurrentDirectory()).toEqual('/'); + }); + it('shows mask before loading file list then hides it at the end', function() { + var showMaskStub = sinon.stub(FileList, 'showMask'); + var hideMaskStub = sinon.stub(FileList, 'hideMask'); + FileList.changeDirectory('/anothersubdir'); + expect(showMaskStub.calledOnce).toEqual(true); + expect(hideMaskStub.calledOnce).toEqual(false); + fakeServer.respond(); + expect(showMaskStub.calledOnce).toEqual(true); + expect(hideMaskStub.calledOnce).toEqual(true); + showMaskStub.restore(); + hideMaskStub.restore(); + }); + it('changes URL to target dir', function() { + FileList.changeDirectory('/somedir'); + expect(pushStateStub.calledOnce).toEqual(true); + expect(pushStateStub.getCall(0).args[0]).toEqual({dir: '/somedir'}); + expect(pushStateStub.getCall(0).args[2]).toEqual(OC.webroot + '/index.php/apps/files?dir=/somedir'); + }); + it('refreshes breadcrumb after update', function() { + var setDirSpy = sinon.spy(FileList.breadcrumb, 'setDirectory'); + FileList.changeDirectory('/anothersubdir'); + fakeServer.respond(); + expect(FileList.breadcrumb.setDirectory.calledOnce).toEqual(true); + expect(FileList.breadcrumb.setDirectory.calledWith('/anothersubdir')).toEqual(true); + setDirSpy.restore(); + }); + }); + describe('breadcrumb events', function() { + beforeEach(function() { + var data = { + status: 'success', + data: { + files: testFiles, + permissions: 31 + } + }; + fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php\?dir=%2Fsubdir/, [ + 200, { + "Content-Type": "application/json" + }, + JSON.stringify(data) + ]); + }); + it('clicking on root breadcrumb changes directory to root', function() { + FileList.changeDirectory('/subdir/two/three with space/four/five'); + fakeServer.respond(); + var changeDirStub = sinon.stub(FileList, 'changeDirectory'); + FileList.breadcrumb.$el.find('.crumb:eq(0)').click(); + + expect(changeDirStub.calledOnce).toEqual(true); + expect(changeDirStub.getCall(0).args[0]).toEqual('/'); + changeDirStub.restore(); + }); + it('clicking on breadcrumb changes directory', function() { + FileList.changeDirectory('/subdir/two/three with space/four/five'); + fakeServer.respond(); + var changeDirStub = sinon.stub(FileList, 'changeDirectory'); + FileList.breadcrumb.$el.find('.crumb:eq(3)').click(); + + expect(changeDirStub.calledOnce).toEqual(true); + expect(changeDirStub.getCall(0).args[0]).toEqual('/subdir/two/three with space'); + changeDirStub.restore(); + }); + it('dropping files on breadcrumb calls move operation', function() { + var request, query, testDir = '/subdir/two/three with space/four/five'; + FileList.changeDirectory(testDir); + fakeServer.respond(); + var $crumb = FileList.breadcrumb.$el.find('.crumb:eq(3)'); + // no idea what this is but is required by the handler + var ui = { + helper: { + find: sinon.stub() + } + }; + // returns a list of tr that were dragged + // FIXME: why are their attributes different than the + // regular file trs ? + ui.helper.find.returns([ + $(''), + $('') + ]); + // simulate drop event + FileList._onDropOnBreadCrumb.call($crumb, new $.Event('drop'), ui); + + // will trigger two calls to move.php (first one was previous list.php) + expect(fakeServer.requests.length).toEqual(3); + + request = fakeServer.requests[1]; + expect(request.method).toEqual('POST'); + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); + query = OC.parseQueryString(request.requestBody); + expect(query).toEqual({ + target: '/subdir/two/three with space', + dir: testDir, + file: 'One.txt' + }); + + request = fakeServer.requests[2]; + expect(request.method).toEqual('POST'); + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); + query = OC.parseQueryString(request.requestBody); + expect(query).toEqual({ + target: '/subdir/two/three with space', + dir: testDir, + file: 'Two.jpg' + }); + }); + it('dropping files on same dir breadcrumb does nothing', function() { + var request, query, testDir = '/subdir/two/three with space/four/five'; + FileList.changeDirectory(testDir); + fakeServer.respond(); + var $crumb = FileList.breadcrumb.$el.find('.crumb:last'); + // no idea what this is but is required by the handler + var ui = { + helper: { + find: sinon.stub() + } + }; + // returns a list of tr that were dragged + // FIXME: why are their attributes different than the + // regular file trs ? + ui.helper.find.returns([ + $(''), + $('') + ]); + // simulate drop event + FileList._onDropOnBreadCrumb.call($crumb, new $.Event('drop'), ui); + + // no extra server request + expect(fakeServer.requests.length).toEqual(1); + }); }); describe('Download Url', function() { it('returns correct download URL for single files', function() { - expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=some%20file.txt'); - expect(FileList.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fanotherpath%2Fabc&files=some%20file.txt'); + expect(Files.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=some%20file.txt'); + expect(Files.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fanotherpath%2Fabc&files=some%20file.txt'); $('#dir').val('/'); - expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=some%20file.txt'); + expect(Files.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=some%20file.txt'); }); it('returns correct download URL for multiple files', function() { - expect(FileList.getDownloadUrl(['a b c.txt', 'd e f.txt'])).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22a%20b%20c.txt%22%2C%22d%20e%20f.txt%22%5D'); + expect(Files.getDownloadUrl(['a b c.txt', 'd e f.txt'])).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22a%20b%20c.txt%22%2C%22d%20e%20f.txt%22%5D'); + }); + it('returns the correct ajax URL', function() { + expect(Files.getAjaxUrl('test', {a:1, b:'x y'})).toEqual(OC.webroot + '/index.php/apps/files/ajax/test.php?a=1&b=x%20y'); }); }); }); diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml index ab47de828b91ce0d71048405591f652ff8c07aa4..15a09a29f51da5b99edfb72bae10fa2b53fc3644 100644 --- a/apps/files_encryption/appinfo/info.xml +++ b/apps/files_encryption/appinfo/info.xml @@ -2,7 +2,7 @@ files_encryption Encryption - The ownCloud files encryption system provides server side-encryption. After the app was enabled you need to re-login to initialize your encryption keys. Please note that server side encryption requires that the ownCloud server admin can be trusted. The main purpose of this app is the encryption of files that are stored on externally mounted storages. + The ownCloud files encryption system provides server side-encryption. After the app is enabled you need to re-login to initialize your encryption keys. Please note that server side encryption requires that the ownCloud server admin can be trusted. The main purpose of this app is the encryption of files that are stored on externally mounted storages. AGPL Sam Tuke, Bjoern Schiessle, Florin Peter 4 diff --git a/apps/files_encryption/l10n/ast.php b/apps/files_encryption/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..7e08e073095487247c93f3b6da960ee610c49b57 --- /dev/null +++ b/apps/files_encryption/l10n/ast.php @@ -0,0 +1,13 @@ + "Contraseña camudada esitosamente.", +"Could not change the password. Maybe the old password was not correct." => "Nun pue camudase la contraseña. Quiciabes la contraseña vieya nun fore correuta.", +"personal settings" => "axustes personales", +"Encryption" => "Cifráu", +"Enabled" => "Habilitáu", +"Disabled" => "Deshabilitáu", +"Change Password" => "Camudar conseña", +" If you don't remember your old password you can ask your administrator to recover your files." => "Si nun recuerdes la to contraseña vieya pues entrugar al to alministrador pa recuperar los tos ficheros.", +"Could not update file recovery" => "Nun pue anovase'l ficheru de recuperación" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/el.php b/apps/files_encryption/l10n/el.php index ad8617bc6d2b9e7e329b5a64b8492f66883278a3..972d7d7138c82fda189fb30b05e03e6eb8115a12 100644 --- a/apps/files_encryption/l10n/el.php +++ b/apps/files_encryption/l10n/el.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Παρακαλώ επιβεβαιώστε ότι η PHP 5.3.3 ή νεότερη είναι εγκατεστημένη και ότι το OpenSSL μαζί με το PHP extension είναι ενεργοποιήμένο και έχει ρυθμιστεί σωστά. Προς το παρόν, η εφαρμογή κρυπτογράφησης είναι απενεργοποιημένη.", "Following users are not set up for encryption:" => "Οι κάτωθι χρήστες δεν έχουν ρυθμιστεί για κρυπογράφηση:", "Initial encryption started... This can take some time. Please wait." => "Η αρχική κρυπτογράφηση άρχισε... Αυτό μπορεί να πάρει κάποια ώρα. Παρακαλώ περιμένετε.", +"Initial encryption running... Please try again later." => "Εκτέλεση αρχικής κρυπτογράφησης... Παρακαλώ προσπαθήστε αργότερα.", "Go directly to your " => "Πηγαίνε απευθείας στο ", "personal settings" => "προσωπικές ρυθμίσεις", "Encryption" => "Κρυπτογράφηση", diff --git a/apps/files_encryption/l10n/et_EE.php b/apps/files_encryption/l10n/et_EE.php index dcf035289fae0bb247e2af2cf8a6ac889b976735..f82f9df9279d0c76fbe2f25dccdd65e3c7ba8765 100644 --- a/apps/files_encryption/l10n/et_EE.php +++ b/apps/files_encryption/l10n/et_EE.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Palun veendu, et on paigaldatud PHP 5.3.3 või uuem ning PHP OpenSSL laiendus on lubatud ning seadistatud korrektselt. Hetkel krüpteerimise rakendus on peatatud.", "Following users are not set up for encryption:" => "Järgmised kasutajad pole seadistatud krüpteeringuks:", "Initial encryption started... This can take some time. Please wait." => "Algne krüpteerimine käivitati... See võib võtta natuke aega. Palun oota.", +"Initial encryption running... Please try again later." => "Toimub esmane krüpteerimine... Palun proovi hiljem uuesti.", "Go directly to your " => "Liigu otse oma", "personal settings" => "isiklikes seadetes", "Encryption" => "Krüpteerimine", diff --git a/apps/files_encryption/l10n/hu_HU.php b/apps/files_encryption/l10n/hu_HU.php index a80c8d6f36d58ce59627573a1aad091a584de966..22c1fa989bd6b16e8981bccb4304ee2a276b1c2a 100644 --- a/apps/files_encryption/l10n/hu_HU.php +++ b/apps/files_encryption/l10n/hu_HU.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Kérem gondoskodjon arról, hogy PHP 5.3.3 vagy annál frissebb legyen telepítve, továbbá az OpenSSL a megfelelő PHP-bővítménnyel együtt rendelkezésre álljon és helyesen legyen konfigurálva! A titkosító modul egyelőre kikapcsolásra került.", "Following users are not set up for encryption:" => "A következő felhasználók nem állították be a titkosítást:", "Initial encryption started... This can take some time. Please wait." => "A titkosítási folyamat megkezdődött... Ez hosszabb ideig is eltarthat. Kérem várjon.", +"Initial encryption running... Please try again later." => "Kezedeti titkosítás fut... Próbálja később.", "Go directly to your " => "Ugrás ide:", "personal settings" => "személyes beállítások", "Encryption" => "Titkosítás", diff --git a/apps/files_encryption/l10n/km.php b/apps/files_encryption/l10n/km.php new file mode 100644 index 0000000000000000000000000000000000000000..0defe6c5388f0616ffb601e92f208112679bdefc --- /dev/null +++ b/apps/files_encryption/l10n/km.php @@ -0,0 +1,11 @@ + "បាន​ប្ដូរ​ពាក្យ​សម្ងាត់​ដោយ​ជោគជ័យ។", +"Could not change the password. Maybe the old password was not correct." => "មិន​អាច​ប្ដូរ​ពាក្យ​សម្ងាត់​បាន​ទេ។ ប្រហែល​ពាក្យ​សម្ងាត់​ចាស់​មិន​ត្រឹម​ត្រូវ។", +"personal settings" => "ការ​កំណត់​ផ្ទាល់​ខ្លួន", +"Encryption" => "កូដនីយកម្ម", +"Enabled" => "បាន​បើក", +"Disabled" => "បាន​បិទ", +"Change Password" => "ប្ដូរ​ពាក្យ​សម្ងាត់" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/ru.php b/apps/files_encryption/l10n/ru.php index bce245ce680296ccee29f14a91401a5ec530d5e9..ba98486893200cf01f125805184b6ecf976fa17a 100644 --- a/apps/files_encryption/l10n/ru.php +++ b/apps/files_encryption/l10n/ru.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Пожалуйста, убедитесь, что версия PHP 5.3.3 или новее, а также, что OpenSSL и соответствующее расширение PHP включены и правильно настроены. На данный момент приложение шифрования отключено.", "Following users are not set up for encryption:" => "Для следующих пользователей шифрование не настроено:", "Initial encryption started... This can take some time. Please wait." => "Начато начальное шифрование... Это может занять какое-то время. Пожалуйста, подождите.", +"Initial encryption running... Please try again later." => "Работает первоначальное шифрование... Пожалуйста, повторите попытку позже.", "Go directly to your " => "Перейти прямо в", "personal settings" => "персональные настройки", "Encryption" => "Шифрование", diff --git a/apps/files_encryption/l10n/sv.php b/apps/files_encryption/l10n/sv.php index 90a9bd73a6f39a773bf109c242bf6b379d844ae2..b17740f25410cb2449d2965b06b01ee7c510623d 100644 --- a/apps/files_encryption/l10n/sv.php +++ b/apps/files_encryption/l10n/sv.php @@ -15,6 +15,8 @@ $TRANSLATIONS = array( "Missing requirements." => "Krav som saknas", "Please make sure that PHP 5.3.3 or newer is installed and that OpenSSL together with the PHP extension is enabled and configured properly. For now, the encryption app has been disabled." => "Kontrollera att PHP 5.3.3 eller senare är installerad och att tillägget OpenSSL PHP är aktiverad och korrekt konfigurerad. Kryptering är tillsvidare inaktiverad.", "Following users are not set up for encryption:" => "Följande användare har inte aktiverat kryptering:", +"Initial encryption started... This can take some time. Please wait." => "Initiala krypteringen har påbörjats... Detta kan ta lite tid. Var god vänta.", +"Initial encryption running... Please try again later." => "Initiala krypteringen körs... Var god försök igen senare.", "Go directly to your " => "Gå direkt till din", "personal settings" => "personliga inställningar", "Encryption" => "Kryptering", diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index caca13aceceec843928e7a43d2c5329f90909413..a4f7bd35497543c000c43358b0118a6c482ef6e6 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -497,13 +497,13 @@ class Crypt { } /** - * @brief Generate a pseudo random 1024kb ASCII key, used as file key + * @brief Generate a pseudo random 256-bit ASCII key, used as file key * @returns $key Generated key */ public static function generateKey() { // Generate key - if ($key = base64_encode(openssl_random_pseudo_bytes(183, $strong))) { + if ($key = base64_encode(openssl_random_pseudo_bytes(32, $strong))) { if (!$strong) { diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index bae1fded53d3376b7b076ab92535548d27a7aaa1..ae2d8d63e23a65912381979e57bc715ba0051b4e 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -3,9 +3,10 @@ /** * ownCloud * - * @author Sam Tuke, Robin Appelman - * @copyright 2012 Sam Tuke samtuke@owncloud.com, Robin Appelman - * icewind1991@gmail.com + * @author Bjoern Schiessle, Sam Tuke, Robin Appelman + * @copyright 2012 Sam Tuke + * 2012 Robin Appelman + * 2014 Bjoern Schiessle * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -36,37 +37,40 @@ namespace OCA\Encryption; */ class Proxy extends \OC_FileProxy { - private static $blackList = null; //mimetypes blacklisted from encryption private static $unencryptedSizes = array(); // remember unencrypted size private static $fopenMode = array(); // remember the fopen mode + private static $enableEncryption = false; // Enable encryption for the given path /** * Check if a file requires encryption * @param string $path + * @param string $mode type of access * @return bool * - * Tests if server side encryption is enabled, and file is allowed by blacklists + * Tests if server side encryption is enabled, and if we should call the + * crypt stream wrapper for the given file */ - private static function shouldEncrypt($path) { + private static function shouldEncrypt($path, $mode = 'w') { $userId = Helper::getUser($path); - if (\OCP\App::isEnabled('files_encryption') === false || Crypt::mode() !== 'server' || - strpos($path, '/' . $userId . '/files') !== 0) { + // don't call the crypt stream wrapper, if... + if ( + \OCP\App::isEnabled('files_encryption') === false // encryption is disabled + || Crypt::mode() !== 'server' // we are not in server-side-encryption mode + || strpos($path, '/' . $userId . '/files') !== 0 // path is not in files/ + || substr($path, 0, 8) === 'crypt://' // we are already in crypt mode + ) { return false; } - if (is_null(self::$blackList)) { - self::$blackList = explode(',', \OCP\Config::getAppValue('files_encryption', 'type_blacklist', '')); - } - - if (Crypt::isCatfileContent($path)) { - return true; - } - - $extension = substr($path, strrpos($path, '.') + 1); + $view = new \OC_FilesystemView(''); + $util = new Util($view, $userId); - if (array_search($extension, self::$blackList) === false) { + // for write operation we always encrypt the files, for read operations + // we check if the existing file is encrypted or not decide if it needs to + // decrypt it. + if (($mode !== 'r' && $mode !== 'rb') || $util->isEncryptedPath($path)) { return true; } @@ -128,6 +132,8 @@ class Proxy extends \OC_FileProxy { // re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; + } else { + return false; } } } @@ -204,23 +210,16 @@ class Proxy extends \OC_FileProxy { } - /** - * @param $path - * @return bool - */ - public function postTouch($path) { - $this->handleFile($path); - - return true; - } - /** * @brief remember initial fopen mode because sometimes it gets changed during the request * @param string $path path * @param string $mode type of access */ public function preFopen($path, $mode) { + self::$fopenMode[$path] = $mode; + self::$enableEncryption = self::shouldEncrypt($path, $mode); + } @@ -233,26 +232,14 @@ class Proxy extends \OC_FileProxy { $path = \OC\Files\Filesystem::normalizePath($path); - if (!$result) { + if (!$result || self::$enableEncryption === false) { return $result; } - // split the path parts - $pathParts = explode('/', $path); - - // don't try to encrypt/decrypt cache chunks or files in the trash bin - if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) { - return $result; - } - - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - // if we remember the mode from the pre proxy we re-use it - // oterwise we fall back to stream_get_meta_data() + // otherwise we fall back to stream_get_meta_data() if (isset(self::$fopenMode[$path])) { $mode = self::$fopenMode[$path]; unset(self::$fopenMode[$path]); @@ -261,35 +248,12 @@ class Proxy extends \OC_FileProxy { $mode = $meta['mode']; } - $view = new \OC_FilesystemView(''); - - $userId = Helper::getUser($path); - $util = new Util($view, $userId); - - // If file is already encrypted, decrypt using crypto protocol - if ( - Crypt::mode() === 'server' - && $util->isEncryptedPath($path) - ) { - - // Close the original encrypted file - fclose($result); + // Close the original encrypted file + fclose($result); - // Open the file using the crypto stream wrapper - // protocol and let it do the decryption work instead - $result = fopen('crypt://' . $path, $mode); - - } elseif ( - self::shouldEncrypt($path) - and $mode !== 'r' - and $mode !== 'rb' - - ) { - $result = fopen('crypt://' . $path, $mode); - } - - // Re-enable the proxy - \OC_FileProxy::$enabled = $proxyStatus; + // Open the file using the crypto stream wrapper + // protocol and let it do the decryption work instead + $result = fopen('crypt://' . $path, $mode); return $result; @@ -402,39 +366,4 @@ class Proxy extends \OC_FileProxy { return $size; } - /** - * @param $path - */ - public function handleFile($path) { - - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; - - $view = new \OC_FilesystemView('/'); - $session = new \OCA\Encryption\Session($view); - $userId = Helper::getUser($path); - $util = new Util($view, $userId); - - // split the path parts - $pathParts = explode('/', $path); - - // get relative path - $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); - - // only if file is on 'files' folder fix file size and sharing - if (isset($pathParts[2]) && $pathParts[2] === 'files' && $util->fixFileSize($path)) { - - // get sharing app state - $sharingEnabled = \OCP\Share::isEnabled(); - - // get users - $usersSharing = $util->getSharingUsersArray($sharingEnabled, $relativePath); - - // update sharing-keys - $util->setSharedFileKeyfiles($session, $usersSharing, $relativePath); - } - - \OC_FileProxy::$enabled = $proxyStatus; - } } diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 58ac03373a737bc2136a5cde4fad3b385114b1fc..df5de558867867f41c38d1c9b2548ada7264d1b6 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -545,7 +545,7 @@ class Stream { $util = new Util($this->rootView, $this->userId); // Get all users sharing the file includes current user - $uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath, $this->userId); + $uniqueUserIds = $util->getSharingUsersArray($sharingEnabled, $this->relPath); $checkedUserIds = $util->filterShareReadyUsers($uniqueUserIds); // Fetch public keys for all sharing users @@ -568,21 +568,25 @@ class Stream { // part file. $path = Helper::stripPartialFileExtension($this->rawPath); - // get file info - $fileInfo = $this->rootView->getFileInfo($path); - if ($fileInfo) { - // set encryption data - $fileInfo['encrypted'] = true; - $fileInfo['size'] = $this->size; - $fileInfo['unencrypted_size'] = $this->unencryptedSize; + $fileInfo = array( + 'encrypted' => true, + 'size' => $this->size, + 'unencrypted_size' => $this->unencryptedSize, + ); - // set fileinfo - $this->rootView->putFileInfo($path, $fileInfo); - } + // set fileinfo + $this->rootView->putFileInfo($path, $fileInfo); + + } + $result = fclose($this->handle); + + if ($result === false) { + \OCP\Util::writeLog('Encryption library', 'Could not close stream, file could be corrupted', \OCP\Util::FATAL); } - return fclose($this->handle); + return $result; + } } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 3db5a423478052c84af1f386c8db99e5ed1176a4..b86815021a8feb4ed9be997dd936b08124ed28d9 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -432,25 +432,28 @@ class Util { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - // we only need 24 byte from the last chunk $data = ''; - $handle = $this->view->fopen($path, 'r'); - if (is_resource($handle)) { - // suppress fseek warining, we handle the case that fseek doesn't - // work in the else branch - if (@fseek($handle, -24, SEEK_END) === 0) { - $data = fgets($handle); - } else { - // if fseek failed on the storage we create a local copy from the file - // and read this one - fclose($handle); - $localFile = $this->view->getLocalFile($path); - $handle = fopen($localFile, 'r'); - if (is_resource($handle) && fseek($handle, -24, SEEK_END) === 0) { + + // we only need 24 byte from the last chunk + if ($this->view->file_exists($path)) { + $handle = $this->view->fopen($path, 'r'); + if (is_resource($handle)) { + // suppress fseek warining, we handle the case that fseek doesn't + // work in the else branch + if (@fseek($handle, -24, SEEK_END) === 0) { $data = fgets($handle); + } else { + // if fseek failed on the storage we create a local copy from the file + // and read this one + fclose($handle); + $localFile = $this->view->getLocalFile($path); + $handle = fopen($localFile, 'r'); + if (is_resource($handle) && fseek($handle, -24, SEEK_END) === 0) { + $data = fgets($handle); + } } + fclose($handle); } - fclose($handle); } // re-enable proxy @@ -1124,8 +1127,9 @@ class Util { * @brief Find, sanitise and format users sharing a file * @note This wraps other methods into a portable bundle * @param boolean $sharingEnabled + * @param string $filePath path relativ to current users files folder */ - public function getSharingUsersArray($sharingEnabled, $filePath, $currentUserId = false) { + public function getSharingUsersArray($sharingEnabled, $filePath) { $appConfig = \OC::$server->getAppConfig(); @@ -1144,12 +1148,14 @@ class Util { $ownerPath = \OCA\Encryption\Helper::stripPartialFileExtension($ownerPath); - $userIds = array(); + // always add owner to the list of users with access to the file + $userIds = array($owner); + if ($sharingEnabled) { // Find out who, if anyone, is sharing the file - $result = \OCP\Share::getUsersSharingFile($ownerPath, $owner, true); - $userIds = $result['users']; + $result = \OCP\Share::getUsersSharingFile($ownerPath, $owner); + $userIds = \array_merge($userIds, $result['users']); if ($result['public']) { $userIds[] = $this->publicShareKeyId; } @@ -1165,11 +1171,6 @@ class Util { $userIds[] = $recoveryKeyId; } - // add current user if given - if ($currentUserId !== false) { - $userIds[] = $currentUserId; - } - // check if it is a group mount if (\OCP\App::isEnabled("files_external")) { $mount = \OC_Mount_Config::getSystemMountPoints(); diff --git a/apps/files_encryption/templates/settings-admin.php b/apps/files_encryption/templates/settings-admin.php index 231a68b6a587d51ed097593b60407da2d55426a1..cf676c445cedbba510a471628b3f8cfaf37121bc 100644 --- a/apps/files_encryption/templates/settings-admin.php +++ b/apps/files_encryption/templates/settings-admin.php @@ -1,63 +1,60 @@ -
-
+ +

t('Encryption')); ?>

-

t('Encryption')); ?>

+

+ t("Enable recovery key (allow to recover users files in case of password loss):")); ?> +
+
+ + +
+ + +
+ /> + t("Enabled")); ?> +
-

- t("Enable recovery key (allow to recover users files in case of password loss):")); ?> -
-
- - -
- - -
- /> - t("Enabled")); ?> -
+ /> + t("Disabled")); ?> +

+

- /> - t("Disabled")); ?> -

+

> + t("Change recovery key password:")); ?>

- -

> - t("Change recovery key password:")); ?> -

- t("Old Recovery key password")); ?> -
-
- t("New Recovery key password")); ?> -
- t("Repeat New Recovery key password")); ?> -
- - -

-
+ t("Old Recovery key password")); ?> +
+
+ t("New Recovery key password")); ?> +
+ t("Repeat New Recovery key password")); ?> +
+ + +

diff --git a/apps/files_encryption/templates/settings-personal.php b/apps/files_encryption/templates/settings-personal.php index 1b4239d82cd78503a76d4a1d41dc7912a7a3820b..8139ece19505e8bc4e4dd619e8c3beb7a14ad4a2 100644 --- a/apps/files_encryption/templates/settings-personal.php +++ b/apps/files_encryption/templates/settings-personal.php @@ -1,66 +1,63 @@ -
-
-

t( 'Encryption' ) ); ?>

+ +

t( 'Encryption' ) ); ?>

- -

- - -
- t( "Set your old private key password to your current log-in password." ) ); ?> - t( " If you don't remember your old password you can ask your administrator to recover your files." ) ); - endif; ?> - -
- - -
- - -
- - -

- - - + +

+ + +
+ t( "Set your old private key password to your current log-in password." ) ); ?> + t( " If you don't remember your old password you can ask your administrator to recover your files." ) ); + endif; ?> + +
+ + +
+ +
-

- -
- t( "Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" ) ); ?> -
- /> - t( "Enabled" ) ); ?> -
+ + +

+ - /> - t( "Disabled" ) ); ?> -
t( 'File recovery settings updated' ) ); ?>
-
t( 'Could not update file recovery' ) ); ?>
-

- + +
+

+ +
+ t( "Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" ) ); ?> +
+ /> + t( "Enabled" ) ); ?> +
-

+ /> + t( "Disabled" ) ); ?> +
t( 'File recovery settings updated' ) ); ?>
+
t( 'Could not update file recovery' ) ); ?>
+

+ diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index be56968ac0992d358bfa76063a58c9ca6d645f69..1f57d7cb635bca44a0f4f84cdc315c23dd65ec1c 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -100,11 +100,11 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { $this->filename = 'share-tmp.test'; - // we don't want to tests with app files_trashbin enabled - \OC_App::disable('files_trashbin'); - // remember files_trashbin state $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin'); + + // we don't want to tests with app files_trashbin enabled + \OC_App::disable('files_trashbin'); } function tearDown() { diff --git a/apps/files_external/3rdparty/phpseclib/LICENSE b/apps/files_external/3rdparty/phpseclib/LICENSE index 6ecd9b9bec11f7587fd76974810a90bb7faad537..75f6b2045c5b50843f38c4338bf25881f38ebbef 100644 --- a/apps/files_external/3rdparty/phpseclib/LICENSE +++ b/apps/files_external/3rdparty/phpseclib/LICENSE @@ -1,4 +1,4 @@ -Copyright 2007-2012 TerraFrost and other contributors +Copyright 2007-2013 TerraFrost and other contributors http://phpseclib.sourceforge.net/ Permission is hereby granted, free of charge, to any person obtaining @@ -18,4 +18,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/apps/files_external/3rdparty/phpseclib/README.md b/apps/files_external/3rdparty/phpseclib/README.md index e90b12f4a6da9dc3bcc79a8ac14ff0b9f7974a95..de528231662b0d47ed6849c8cc45097a6523cbdc 100644 --- a/apps/files_external/3rdparty/phpseclib/README.md +++ b/apps/files_external/3rdparty/phpseclib/README.md @@ -6,11 +6,11 @@ MIT-licensed pure-PHP implementations of an arbitrary-precision integer arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael, AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509 -* [Download (0.3.5)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.5.zip/download) +* [Download (0.3.6)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.6.zip/download) * [Browse Git](https://github.com/phpseclib/phpseclib) * [Documentation](http://phpseclib.sourceforge.net/) * [Support](http://www.frostjedi.com/phpbb/viewforum.php?f=46) -* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/latest/) +* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/latest/) PEAR Channel PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm) diff --git a/apps/files_external/3rdparty/phpseclib/composer.json b/apps/files_external/3rdparty/phpseclib/composer.json index 79c92b52e47759e7d34e738b0202ca98e41cfa95..70f4f7c36e9412fb64849a9a66d9e0c8f1d4d8ff 100644 --- a/apps/files_external/3rdparty/phpseclib/composer.json +++ b/apps/files_external/3rdparty/phpseclib/composer.json @@ -11,6 +11,8 @@ "signing", "rsa", "aes", + "blowfish", + "twofish", "ssh", "sftp", "x509", @@ -25,16 +27,34 @@ { "name": "Jim Wigginton", "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", "role": "Developer" } ], "require": { "php": ">=5.0.0" }, + "require-dev": { + "squizlabs/php_codesniffer": "1.*" + }, "suggest": { "ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.", "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", - "pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP >= 4.3.3." + "pear-pear/PHP_Compat": "Install PHP_Compat to get phpseclib working on PHP < 4.3.3." }, "include-path": ["phpseclib/"], "autoload": { @@ -42,7 +62,8 @@ "Crypt": "phpseclib/", "File": "phpseclib/", "Math": "phpseclib/", - "Net": "phpseclib/" + "Net": "phpseclib/", + "System": "phpseclib/" }, "files": [ "phpseclib/Crypt/Random.php" diff --git a/apps/files_external/3rdparty/phpseclib/composer.lock b/apps/files_external/3rdparty/phpseclib/composer.lock new file mode 100644 index 0000000000000000000000000000000000000000..1b5ff07e484bb920a8d9add230abf4456a2ae7a1 --- /dev/null +++ b/apps/files_external/3rdparty/phpseclib/composer.lock @@ -0,0 +1,95 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + ], + "hash": "4975b8cde04a99d6e78e108753845af6", + "packages": [ + + ], + "packages-dev": [ + { + "name": "squizlabs/php_codesniffer", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "a76a39b317ce8106abe6264daa505e24e1731860" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/a76a39b317ce8106abe6264daa505e24e1731860", + "reference": "a76a39b317ce8106abe6264daa505e24e1731860", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.1.2" + }, + "suggest": { + "phpunit/php-timer": "dev-master" + }, + "bin": [ + "scripts/phpcs" + ], + "type": "library", + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/CommentParser/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2014-02-04 23:49:58" + } + ], + "aliases": [ + + ], + "minimum-stability": "stable", + "stability-flags": [ + + ], + "platform": { + "php": ">=5.0.0" + }, + "platform-dev": [ + + ] +} diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/AES.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/AES.php index 81fa2feab66bc09569a807fbffbf470a4097b20c..cf8c050a59e82b00eb4e0b2c4aeabceb732ba663 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/AES.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/AES.php @@ -1,5 +1,4 @@ - * @copyright MMVIII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_AES + * @author Jim Wigginton + * @copyright MMVIII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** * Include Crypt_Rijndael */ if (!class_exists('Crypt_Rijndael')) { - require_once('Rijndael.php'); + include_once 'Rijndael.php'; } /**#@+ @@ -125,12 +124,13 @@ define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT); /** * Pure-PHP implementation of AES. * + * @package Crypt_AES * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_AES */ -class Crypt_AES extends Crypt_Rijndael { +class Crypt_AES extends Crypt_Rijndael +{ /** * The namespace used by the cipher for its constants. * @@ -183,6 +183,3 @@ class Crypt_AES extends Crypt_Rijndael { return; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Base.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Base.php index 7c650ca729b1d93f5aeeae621498e98713b5cde6..f08529b902b1148cea6af277794c710438b36827 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Base.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Base.php @@ -1,5 +1,4 @@ - * @author Hans-Juergen Petrich - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 1.0.1 - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_Base + * @author Jim Wigginton + * @author Hans-Juergen Petrich + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 1.0.1 + * @link http://phpseclib.sourceforge.net */ /**#@+ @@ -115,13 +114,14 @@ define('CRYPT_MODE_MCRYPT', 2); /** * Base Class for all Crypt_* cipher classes * + * @package Crypt_Base * @author Jim Wigginton * @author Hans-Juergen Petrich * @version 1.0.0 * @access public - * @package Crypt_Base */ -class Crypt_Base { +class Crypt_Base +{ /** * The Encryption Mode * @@ -582,7 +582,7 @@ class Crypt_Base { case !function_exists('hash_algos'): case !in_array($hash, hash_algos()): if (!class_exists('Crypt_Hash')) { - require_once('Crypt/Hash.php'); + include_once 'Crypt/Hash.php'; } $i = 1; while (strlen($key) < $dkLen) { @@ -1984,6 +1984,3 @@ class Crypt_Base { return $functions; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Blowfish.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Blowfish.php index c8ef67e8f7cacb9c790319cfdda36f093046ed9b..b352e7c468887a2abe3fd595f21dcfcdb9216136 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Blowfish.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Blowfish.php @@ -1,5 +1,4 @@ - * @author Hans-Juergen Petrich - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 1.0 - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_Blowfish + * @author Jim Wigginton + * @author Hans-Juergen Petrich + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 1.0 + * @link http://phpseclib.sourceforge.net */ /** @@ -61,7 +60,7 @@ * Base cipher class */ if (!class_exists('Crypt_Base')) { - require_once('Base.php'); + include_once 'Base.php'; } /**#@+ @@ -120,13 +119,14 @@ define('CRYPT_BLOWFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT); /** * Pure-PHP implementation of Blowfish. * + * @package Crypt_Blowfish * @author Jim Wigginton * @author Hans-Juergen Petrich * @version 1.0 * @access public - * @package Crypt_Blowfish */ -class Crypt_Blowfish extends Crypt_Base { +class Crypt_Blowfish extends Crypt_Base +{ /** * Block Length of the cipher * @@ -418,8 +418,7 @@ class Crypt_Blowfish extends Crypt_Base { if (!$keylength) { $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - } - elseif ($keylength > 56) { + } elseif ($keylength > 56) { $key = substr($key, 0, 56); } @@ -673,6 +672,3 @@ class Crypt_Blowfish extends Crypt_Base { $this->inline_crypt = $lambda_functions[$code_hash]; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/DES.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/DES.php index 8b04210659d8ea8018940cef35b33b41b0702b3e..fcbf01993a1cdae275bbc094d9c27eaae1107e52 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/DES.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/DES.php @@ -1,5 +1,4 @@ - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_DES + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** @@ -65,7 +64,7 @@ * Base cipher class */ if (!class_exists('Crypt_Base')) { - require_once('Base.php'); + include_once 'Base.php'; } /**#@+ @@ -139,12 +138,13 @@ define('CRYPT_DES_MODE_MCRYPT', CRYPT_MODE_MCRYPT); /** * Pure-PHP implementation of DES. * + * @package Crypt_DES * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_DES */ -class Crypt_DES extends Crypt_Base { +class Crypt_DES extends Crypt_Base +{ /** * Block Length of the cipher * @@ -1336,12 +1336,14 @@ class Crypt_DES extends Crypt_Base { $pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF]; // Reorder: odd bytes/even bytes. Push the result in key schedule. - $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = - $keys[$des_round][CRYPT_DES_DECRYPT][$ki - 1] = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) | - (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); - $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = - $keys[$des_round][CRYPT_DES_DECRYPT][$ki ] = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) | - (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); + $val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) | + (($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF); + $val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) | + (($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF); + $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val1; + $keys[$des_round][CRYPT_DES_DECRYPT][$ki - 1] = $val1; + $keys[$des_round][CRYPT_DES_ENCRYPT][ ] = $val2; + $keys[$des_round][CRYPT_DES_DECRYPT][$ki ] = $val2; } } @@ -1531,6 +1533,3 @@ class Crypt_DES extends Crypt_Base { $this->inline_crypt = $lambda_functions[$code_hash]; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Hash.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Hash.php index 21897241989e6be02a4c5af5a6b5da3ab23937f3..b156169d68b5d21e640a07e5748a499ac928158b 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Hash.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Hash.php @@ -1,5 +1,4 @@ - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_Hash + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /**#@+ @@ -76,12 +75,13 @@ define('CRYPT_HASH_MODE_HASH', 3); /** * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. * + * @package Crypt_Hash * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_Hash */ -class Crypt_Hash { +class Crypt_Hash +{ /** * Hash Parameter * @@ -581,7 +581,7 @@ class Crypt_Hash { function _sha512($m) { if (!class_exists('Math_BigInteger')) { - require_once('Math/BigInteger.php'); + include_once 'Math/BigInteger.php'; } static $init384, $init512, $k; @@ -589,11 +589,11 @@ class Crypt_Hash { if (!isset($k)) { // Initialize variables $init384 = array( // initial values for SHA384 - 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', + 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4' ); $init512 = array( // initial values for SHA512 - '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', + '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179' ); diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC2.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC2.php index 5e0ca88c8fc160c6df5ff59e5bccb9db8ee44a6e..de22d631a162af5be11b1aea07d35ed99239f3cc 100755 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC2.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC2.php @@ -1,5 +1,4 @@ - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_RC2 + * @author Patrick Monnerat + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** @@ -58,7 +57,7 @@ * Base cipher class */ if (!class_exists('Crypt_Base')) { - require_once('Base.php'); + include_once 'Base.php'; } /**#@+ @@ -117,11 +116,12 @@ define('CRYPT_RC2_MODE_MCRYPT', CRYPT_MODE_MCRYPT); /** * Pure-PHP implementation of RC2. * + * @package Crypt_RC2 * @version 0.1.1 * @access public - * @package Crypt_RC2 */ -class Crypt_RC2 extends Crypt_Base { +class Crypt_RC2 extends Crypt_Base +{ /** * Block Length of the cipher * @@ -651,6 +651,3 @@ class Crypt_RC2 extends Crypt_Base { $this->inline_crypt = $lambda_functions[$code_hash]; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC4.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC4.php index f6a9eae2fb72a129b4f018712a8b5f5a59d0c2f7..d062be2573f041e3e52189afba3578dd8460fa87 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC4.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RC4.php @@ -1,5 +1,4 @@ - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_RC4 + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** @@ -67,7 +66,7 @@ * Base cipher class */ if (!class_exists('Crypt_Base')) { - require_once('Base.php'); + include_once 'Base.php'; } /**#@+ @@ -95,20 +94,21 @@ define('CRYPT_RC4_DECRYPT', 1); /** * Pure-PHP implementation of RC4. * + * @package Crypt_RC4 * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_RC4 */ -class Crypt_RC4 extends Crypt_Base { +class Crypt_RC4 extends Crypt_Base +{ /** * Block Length of the cipher * - * RC4 is a stream cipher + * RC4 is a stream cipher * so we the block_size to 0 * * @see Crypt_Base::block_size - * @var Integer + * @var Integer * @access private */ var $block_size = 0; @@ -132,7 +132,6 @@ class Crypt_RC4 extends Crypt_Base { */ var $const_namespace = 'RC4'; - /** * The mcrypt specific name of the cipher * @@ -332,6 +331,3 @@ class Crypt_RC4 extends Crypt_Base { return $text; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RSA.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RSA.php index 92ebfdf7236d22e75197c14a8371b2526c401c31..feb887c70318e0a4308214878a43d344a9cb61dd 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RSA.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/RSA.php @@ -1,5 +1,4 @@ - * @copyright MMIX Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_RSA + * @author Jim Wigginton + * @copyright MMIX Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** @@ -73,17 +72,17 @@ */ // the class_exists() will only be called if the crypt_random_string function hasn't been defined and // will trigger a call to __autoload() if you're wanting to auto-load classes -// call function_exists() a second time to stop the require_once from being called outside +// call function_exists() a second time to stop the include_once from being called outside // of the auto loader if (!function_exists('crypt_random_string')) { - require_once('Random.php'); + include_once 'Random.php'; } /** * Include Crypt_Hash */ if (!class_exists('Crypt_Hash')) { - require_once('Hash.php'); + include_once 'Hash.php'; } /**#@+ @@ -145,7 +144,7 @@ define('CRYPT_RSA_ASN1_INTEGER', 2); /** * ASN1 Bit String */ -define('CRYPT_RSA_ASN1_BITSTRING', 3); +define('CRYPT_RSA_ASN1_BITSTRING', 3); /** * ASN1 Sequence (with the constucted bit set) */ @@ -240,12 +239,13 @@ define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 7); /** * Pure-PHP PKCS#1 compliant implementation of RSA. * + * @package Crypt_RSA * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_RSA */ -class Crypt_RSA { +class Crypt_RSA +{ /** * Precomputed Zero * @@ -433,7 +433,7 @@ class Crypt_RSA { /** * OpenSSL configuration file name. * - * Set to NULL to use system configuration file. + * Set to null to use system configuration file. * @see Crypt_RSA::createKey() * @var Mixed * @Access public @@ -461,7 +461,7 @@ class Crypt_RSA { function Crypt_RSA() { if (!class_exists('Math_BigInteger')) { - require_once('Math/BigInteger.php'); + include_once 'Math/BigInteger.php'; } $this->configFile = CRYPT_RSA_OPENSSL_CONFIG; @@ -555,7 +555,7 @@ class Crypt_RSA { $config['config'] = $this->configFile; } $rsa = openssl_pkey_new(array('private_key_bits' => $bits) + $config); - openssl_pkey_export($rsa, $privatekey, NULL, $config); + openssl_pkey_export($rsa, $privatekey, null, $config); $publickey = openssl_pkey_get_details($rsa); $publickey = $publickey['key']; @@ -773,7 +773,7 @@ class Crypt_RSA { $private.= crypt_random_string(16 - (strlen($private) & 15)); $source.= pack('Na*', strlen($private), $private); if (!class_exists('Crypt_AES')) { - require_once('Crypt/AES.php'); + include_once 'Crypt/AES.php'; } $sequence = 0; $symkey = ''; @@ -794,7 +794,7 @@ class Crypt_RSA { $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; $key.= chunk_split($private, 64); if (!class_exists('Crypt_Hash')) { - require_once('Crypt/Hash.php'); + include_once 'Crypt/Hash.php'; } $hash = new Crypt_Hash('sha1'); $hash->setKey(pack('H*', sha1($hashkey))); @@ -834,7 +834,7 @@ class Crypt_RSA { $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $des = new Crypt_TripleDES(); $des->setKey($symkey); @@ -984,7 +984,7 @@ class Crypt_RSA { DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's - own implementation. ie. the implementation *is* the standard and any bugs that may exist in that + own implementation. ie. the implementation *is* the standard and any bugs that may exist in that implementation are part of the standard, as well. * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ @@ -992,41 +992,42 @@ class Crypt_RSA { $iv = pack('H*', trim($matches[2])); $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8))); - $ciphertext = preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-| #s', '', $key); - $ciphertext = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false; + // remove the Proc-Type / DEK-Info sections as they're no longer needed + $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); + $ciphertext = $this->_extractBER($key); if ($ciphertext === false) { $ciphertext = $key; } switch ($matches[1]) { case 'AES-256-CBC': if (!class_exists('Crypt_AES')) { - require_once('Crypt/AES.php'); + include_once 'Crypt/AES.php'; } $crypto = new Crypt_AES(); break; case 'AES-128-CBC': if (!class_exists('Crypt_AES')) { - require_once('Crypt/AES.php'); + include_once 'Crypt/AES.php'; } $symkey = substr($symkey, 0, 16); $crypto = new Crypt_AES(); break; case 'DES-EDE3-CFB': if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $crypto = new Crypt_TripleDES(CRYPT_DES_MODE_CFB); break; case 'DES-EDE3-CBC': if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $symkey = substr($symkey, 0, 24); $crypto = new Crypt_TripleDES(); break; case 'DES-CBC': if (!class_exists('Crypt_DES')) { - require_once('Crypt/DES.php'); + include_once 'Crypt/DES.php'; } $crypto = new Crypt_DES(); break; @@ -1037,8 +1038,7 @@ class Crypt_RSA { $crypto->setIV($iv); $decoded = $crypto->decrypt($ciphertext); } else { - $decoded = preg_replace('#-.+-|[\r\n]| #', '', $key); - $decoded = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $decoded) ? base64_decode($decoded) : false; + $decoded = $this->_extractBER($key); } if ($decoded !== false) { @@ -1240,7 +1240,7 @@ class Crypt_RSA { switch ($encryption) { case 'aes256-cbc': if (!class_exists('Crypt_AES')) { - require_once('Crypt/AES.php'); + include_once 'Crypt/AES.php'; } $symkey = ''; $sequence = 0; @@ -1452,7 +1452,7 @@ class Crypt_RSA { break; } } - + } else { $components = $this->_parseKey($key, $type); } @@ -2152,7 +2152,7 @@ class Crypt_RSA { * * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}. The fact that the error * messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2: - * + * * Note. Care must be taken to ensure that an opponent cannot * distinguish the different error conditions in Step 3.g, whether by * error message or timing, or, more generally, learn partial @@ -2781,4 +2781,31 @@ class Crypt_RSA { return $this->_rsassa_pss_verify($message, $signature); } } + + /** + * Extract raw BER from Base64 encoding + * + * @access private + * @param String $str + * @return String + */ + function _extractBER($str) + { + /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them + * above and beyond the ceritificate. + * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: + * + * Bag Attributes + * localKeyID: 01 00 00 00 + * subject=/O=organization/OU=org unit/CN=common name + * issuer=/O=organization/CN=common name + */ + $temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1); + // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff + $temp = preg_replace('#-+[^-]+-+#', '', $temp); + // remove new lines + $temp = str_replace(array("\r", "\n", ' '), '', $temp); + $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; + return $temp != false ? $temp : $str; + } } diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Random.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Random.php index 8532aab5a5913d9acdaf84d3afe978171cccb3c2..977ec79726b2a16c9259cc230ca240a3ee4e8f92 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Random.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Random.php @@ -1,5 +1,4 @@ - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_Random + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** @@ -132,9 +131,7 @@ function crypt_random_string($length) $old_session_id = session_id(); $old_use_cookies = ini_get('session.use_cookies'); $old_session_cache_limiter = session_cache_limiter(); - if (isset($_SESSION)) { - $_OLD_SESSION = $_SESSION; - } + $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false; if ($old_session_id != '') { session_write_close(); } @@ -167,7 +164,7 @@ function crypt_random_string($length) ini_set('session.use_cookies', $old_use_cookies); session_cache_limiter($old_session_cache_limiter); } else { - if (isset($_OLD_SESSION)) { + if ($_OLD_SESSION !== false) { $_SESSION = $_OLD_SESSION; unset($_OLD_SESSION); } else { diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Rijndael.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Rijndael.php index c63e0ff7e3f4c7ef07add63b4b72886ea0675c2a..42531516cf84fe16d9f6f5b4418b530f5f8e9d81 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Rijndael.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Rijndael.php @@ -1,5 +1,4 @@ - * @copyright MMVIII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_Rijndael + * @author Jim Wigginton + * @copyright MMVIII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** @@ -77,7 +76,7 @@ * Base cipher class */ if (!class_exists('Crypt_Base')) { - require_once('Base.php'); + include_once 'Base.php'; } /**#@+ @@ -136,12 +135,13 @@ define('CRYPT_RIJNDAEL_MODE_MCRYPT', CRYPT_MODE_MCRYPT); /** * Pure-PHP implementation of Rijndael. * + * @package Crypt_Rijndael * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_Rijndael */ -class Crypt_Rijndael extends Crypt_Base { +class Crypt_Rijndael extends Crypt_Base +{ /** * The default password key_size used by setPassword() * @@ -1369,6 +1369,3 @@ class Crypt_Rijndael extends Crypt_Base { $this->inline_crypt = $lambda_functions[$code_hash]; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/TripleDES.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/TripleDES.php index 4030c6c9fbe15c6d74593cfe7198033750ac5342..21318209fe296c6fcf168856fbc01818b7d5ac59 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/TripleDES.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/TripleDES.php @@ -1,5 +1,4 @@ - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_TripleDES + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** * Include Crypt_DES */ if (!class_exists('Crypt_DES')) { - require_once('DES.php'); + include_once 'DES.php'; } /** @@ -77,12 +76,13 @@ define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC); /** * Pure-PHP implementation of Triple DES. * + * @package Crypt_TripleDES * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Crypt_TripleDES */ -class Crypt_TripleDES extends Crypt_DES { +class Crypt_TripleDES extends Crypt_DES +{ /** * The default password key_size used by setPassword() * @@ -417,6 +417,3 @@ class Crypt_TripleDES extends Crypt_DES { parent::_setupKey(); } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Twofish.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Twofish.php index 6342298d1a3a221de75a9eaf8641172328a7c8e5..9be5fd10997101c40532b7a8de52bef602460336 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Twofish.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Crypt/Twofish.php @@ -1,5 +1,4 @@ - * @author Hans-Juergen Petrich - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 1.0 - * @link http://phpseclib.sourceforge.net + * @category Crypt + * @package Crypt_Twofish + * @author Jim Wigginton + * @author Hans-Juergen Petrich + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @version 1.0 + * @link http://phpseclib.sourceforge.net */ /** @@ -61,7 +60,7 @@ * Base cipher class */ if (!class_exists('Crypt_Base')) { - require_once('Base.php'); + include_once 'Base.php'; } /**#@+ @@ -120,13 +119,14 @@ define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT); /** * Pure-PHP implementation of Twofish. * + * @package Crypt_Twofish * @author Jim Wigginton * @author Hans-Juergen Petrich * @version 1.0 * @access public - * @package Crypt_Twofish */ -class Crypt_Twofish extends Crypt_Base { +class Crypt_Twofish extends Crypt_Base +{ /** * The namespace used by the cipher for its constants. * @@ -919,6 +919,3 @@ class Crypt_Twofish extends Crypt_Base { $this->inline_crypt = $lambda_functions[$code_hash]; } } - -// vim: ts=4:sw=4:et: -// vim6: fdl=1: diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/File/ANSI.php b/apps/files_external/3rdparty/phpseclib/phpseclib/File/ANSI.php index f7ac85536f8fdc61591c0c0b2bea80750221c149..0e0004ce27dd7acc809b30487265e8853d760691 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/File/ANSI.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/File/ANSI.php @@ -1,5 +1,4 @@ - * @copyright MMXII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category File + * @package File_ANSI + * @author Jim Wigginton + * @copyright MMXII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** * Pure-PHP ANSI Decoder * + * @package File_ANSI * @author Jim Wigginton * @version 0.3.0 * @access public - * @package File_ANSI */ -class File_ANSI { +class File_ANSI +{ /** * Max Width * @@ -557,4 +557,4 @@ class File_ANSI { return '
' . $scrollback . '
'; } -} \ No newline at end of file +} diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/File/ASN1.php b/apps/files_external/3rdparty/phpseclib/phpseclib/File/ASN1.php index 9f481fc3ccb81641677ac07a8816c81cf7bcf5ee..67d1f6dc7901c315e0fc1e06440f5521b5ab6fda 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/File/ASN1.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/File/ASN1.php @@ -1,5 +1,4 @@ - * @copyright MMXII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category File + * @package File_ASN1 + * @author Jim Wigginton + * @copyright MMXII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /**#@+ @@ -58,21 +57,21 @@ define('FILE_ASN1_CLASS_PRIVATE', 3); * @access private * @link http://www.obj-sys.com/asn1tutorial/node124.html */ -define('FILE_ASN1_TYPE_BOOLEAN', 1); -define('FILE_ASN1_TYPE_INTEGER', 2); -define('FILE_ASN1_TYPE_BIT_STRING', 3); -define('FILE_ASN1_TYPE_OCTET_STRING', 4); -define('FILE_ASN1_TYPE_NULL', 5); -define('FILE_ASN1_TYPE_OBJECT_IDENTIFIER',6); -//define('FILE_ASN1_TYPE_OBJECT_DESCRIPTOR',7); -//define('FILE_ASN1_TYPE_INSTANCE_OF', 8); // EXTERNAL -define('FILE_ASN1_TYPE_REAL', 9); -define('FILE_ASN1_TYPE_ENUMERATED', 10); -//define('FILE_ASN1_TYPE_EMBEDDED', 11); -define('FILE_ASN1_TYPE_UTF8_STRING', 12); -//define('FILE_ASN1_TYPE_RELATIVE_OID', 13); -define('FILE_ASN1_TYPE_SEQUENCE', 16); // SEQUENCE OF -define('FILE_ASN1_TYPE_SET', 17); // SET OF +define('FILE_ASN1_TYPE_BOOLEAN', 1); +define('FILE_ASN1_TYPE_INTEGER', 2); +define('FILE_ASN1_TYPE_BIT_STRING', 3); +define('FILE_ASN1_TYPE_OCTET_STRING', 4); +define('FILE_ASN1_TYPE_NULL', 5); +define('FILE_ASN1_TYPE_OBJECT_IDENTIFIER', 6); +//define('FILE_ASN1_TYPE_OBJECT_DESCRIPTOR', 7); +//define('FILE_ASN1_TYPE_INSTANCE_OF', 8); // EXTERNAL +define('FILE_ASN1_TYPE_REAL', 9); +define('FILE_ASN1_TYPE_ENUMERATED', 10); +//define('FILE_ASN1_TYPE_EMBEDDED', 11); +define('FILE_ASN1_TYPE_UTF8_STRING', 12); +//define('FILE_ASN1_TYPE_RELATIVE_OID', 13); +define('FILE_ASN1_TYPE_SEQUENCE', 16); // SEQUENCE OF +define('FILE_ASN1_TYPE_SET', 17); // SET OF /**#@-*/ /**#@+ * More Tag Classes @@ -80,19 +79,19 @@ define('FILE_ASN1_TYPE_SET', 17); // SET OF * @access private * @link http://www.obj-sys.com/asn1tutorial/node10.html */ -define('FILE_ASN1_TYPE_NUMERIC_STRING', 18); -define('FILE_ASN1_TYPE_PRINTABLE_STRING',19); -define('FILE_ASN1_TYPE_TELETEX_STRING', 20); // T61String -define('FILE_ASN1_TYPE_VIDEOTEX_STRING', 21); -define('FILE_ASN1_TYPE_IA5_STRING', 22); -define('FILE_ASN1_TYPE_UTC_TIME', 23); -define('FILE_ASN1_TYPE_GENERALIZED_TIME',24); -define('FILE_ASN1_TYPE_GRAPHIC_STRING', 25); -define('FILE_ASN1_TYPE_VISIBLE_STRING', 26); // ISO646String -define('FILE_ASN1_TYPE_GENERAL_STRING', 27); -define('FILE_ASN1_TYPE_UNIVERSAL_STRING',28); -//define('FILE_ASN1_TYPE_CHARACTER_STRING',29); -define('FILE_ASN1_TYPE_BMP_STRING', 30); +define('FILE_ASN1_TYPE_NUMERIC_STRING', 18); +define('FILE_ASN1_TYPE_PRINTABLE_STRING', 19); +define('FILE_ASN1_TYPE_TELETEX_STRING', 20); // T61String +define('FILE_ASN1_TYPE_VIDEOTEX_STRING', 21); +define('FILE_ASN1_TYPE_IA5_STRING', 22); +define('FILE_ASN1_TYPE_UTC_TIME', 23); +define('FILE_ASN1_TYPE_GENERALIZED_TIME', 24); +define('FILE_ASN1_TYPE_GRAPHIC_STRING', 25); +define('FILE_ASN1_TYPE_VISIBLE_STRING', 26); // ISO646String +define('FILE_ASN1_TYPE_GENERAL_STRING', 27); +define('FILE_ASN1_TYPE_UNIVERSAL_STRING', 28); +//define('FILE_ASN1_TYPE_CHARACTER_STRING', 29); +define('FILE_ASN1_TYPE_BMP_STRING', 30); /**#@-*/ /**#@+ @@ -111,12 +110,13 @@ define('FILE_ASN1_TYPE_ANY', -2); * * Bypass normal encoding rules in File_ASN1::encodeDER() * + * @package File_ASN1 * @author Jim Wigginton * @version 0.3.0 * @access public - * @package File_ASN1 */ -class File_ASN1_Element { +class File_ASN1_Element +{ /** * Raw element value * @@ -141,12 +141,13 @@ class File_ASN1_Element { /** * Pure-PHP ASN.1 Parser * + * @package File_ASN1 * @author Jim Wigginton * @version 0.3.0 * @access public - * @package File_ASN1 */ -class File_ASN1 { +class File_ASN1 +{ /** * ASN.1 object identifier * @@ -252,7 +253,7 @@ class File_ASN1 { if (!$static_init) { $static_init = true; if (!class_exists('Math_BigInteger')) { - require_once('Math/BigInteger.php'); + include_once 'Math/BigInteger.php'; } } } @@ -316,7 +317,7 @@ class File_ASN1 { $length = ord($this->_string_shift($encoded)); $start++; if ( $length == 0x80 ) { // indefinite length - // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all + // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all // immediately available." -- paragraph 8.1.3.2.c //if ( !$constructed ) { // return false; @@ -419,7 +420,7 @@ class File_ASN1 { //} $current['content'].= $temp[$i]['content']; } - // $length = + // $length = } break; case FILE_ASN1_TYPE_NULL: @@ -456,7 +457,7 @@ class File_ASN1 { -- X.690-0207.pdf#page=23 (paragraph 8.21.3) - Per that, we're not going to do any validation. If there are any illegal characters in the string, + Per that, we're not going to do any validation. If there are any illegal characters in the string, we don't really care */ case FILE_ASN1_TYPE_NUMERIC_STRING: // 0,1,2,3,4,5,6,7,8,9, and space @@ -545,13 +546,13 @@ class File_ASN1 { return array($key => $value); } } - return NULL; + return null; case isset($mapping['implicit']): case isset($mapping['explicit']): case $decoded['type'] == $mapping['type']: break; default: - return NULL; + return null; } if (isset($mapping['implicit'])) { @@ -566,8 +567,8 @@ class File_ASN1 { if (isset($mapping['min']) && isset($mapping['max'])) { $child = $mapping['children']; foreach ($decoded['content'] as $content) { - if (($map[] = $this->asn1map($content, $child, $special)) === NULL) { - return NULL; + if (($map[] = $this->asn1map($content, $child, $special)) === null) { + return null; } } @@ -585,15 +586,14 @@ class File_ASN1 { if ($child['type'] != FILE_ASN1_TYPE_CHOICE) { // Get the mapping and input class & constant. $childClass = $tempClass = FILE_ASN1_CLASS_UNIVERSAL; - $constant = NULL; + $constant = null; if (isset($temp['constant'])) { $tempClass = isset($temp['class']) ? $temp['class'] : FILE_ASN1_CLASS_CONTEXT_SPECIFIC; } if (isset($child['class'])) { $childClass = $child['class']; $constant = $child['cast']; - } - elseif (isset($child['constant'])) { + } elseif (isset($child['constant'])) { $childClass = FILE_ASN1_CLASS_CONTEXT_SPECIFIC; $constant = $child['constant']; } @@ -611,7 +611,7 @@ class File_ASN1 { if ($maymatch) { // Attempt submapping. $candidate = $this->asn1map($temp, $child, $special); - $maymatch = $candidate !== NULL; + $maymatch = $candidate !== null; } if ($maymatch) { @@ -624,12 +624,12 @@ class File_ASN1 { } elseif (isset($child['default'])) { $map[$key] = $child['default']; // Use default. } elseif (!isset($child['optional'])) { - return NULL; // Syntax error. + return null; // Syntax error. } } // Fail mapping if all input items have not been consumed. - return $i < $n? NULL: $map; + return $i < $n? null: $map; // the main diff between sets and sequences is the encapsulation of the foreach in another for loop case FILE_ASN1_TYPE_SET: @@ -639,8 +639,8 @@ class File_ASN1 { if (isset($mapping['min']) && isset($mapping['max'])) { $child = $mapping['children']; foreach ($decoded['content'] as $content) { - if (($map[] = $this->asn1map($content, $child, $special)) === NULL) { - return NULL; + if (($map[] = $this->asn1map($content, $child, $special)) === null) { + return null; } } @@ -661,12 +661,11 @@ class File_ASN1 { $maymatch = true; if ($child['type'] != FILE_ASN1_TYPE_CHOICE) { $childClass = FILE_ASN1_CLASS_UNIVERSAL; - $constant = NULL; + $constant = null; if (isset($child['class'])) { $childClass = $child['class']; $constant = $child['cast']; - } - elseif (isset($child['constant'])) { + } elseif (isset($child['constant'])) { $childClass = FILE_ASN1_CLASS_CONTEXT_SPECIFIC; $constant = $child['constant']; } @@ -683,7 +682,7 @@ class File_ASN1 { if ($maymatch) { // Attempt submapping. $candidate = $this->asn1map($temp, $child, $special); - $maymatch = $candidate !== NULL; + $maymatch = $candidate !== null; } if (!$maymatch) { @@ -704,7 +703,7 @@ class File_ASN1 { if (isset($child['default'])) { $map[$key] = $child['default']; } elseif (!isset($child['optional'])) { - return NULL; + return null; } } } @@ -797,7 +796,7 @@ class File_ASN1 { function encodeDER($source, $mapping, $special = array()) { $this->location = array(); - return $this->_encode_der($source, $mapping, NULL, $special); + return $this->_encode_der($source, $mapping, null, $special); } /** @@ -819,7 +818,7 @@ class File_ASN1 { * @return String * @access private */ - function _encode_der($source, $mapping, $idx = NULL, $special = array()) + function _encode_der($source, $mapping, $idx = null, $special = array()) { if (is_object($source) && strtolower(get_class($source)) == 'file_asn1_element') { return $source->element; @@ -850,7 +849,7 @@ class File_ASN1 { $child = $mapping['children']; foreach ($source as $content) { - $temp = $this->_encode_der($content, $child, NULL, $special); + $temp = $this->_encode_der($content, $child, null, $special); if ($temp === false) { return false; } @@ -1030,19 +1029,19 @@ class File_ASN1 { switch (true) { case !isset($source): - return $this->_encode_der(NULL, array('type' => FILE_ASN1_TYPE_NULL) + $mapping, NULL, $special); + return $this->_encode_der(null, array('type' => FILE_ASN1_TYPE_NULL) + $mapping, null, $special); case is_int($source): case is_object($source) && strtolower(get_class($source)) == 'math_biginteger': - return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping, NULL, $special); + return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping, null, $special); case is_float($source): - return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping, NULL, $special); + return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping, null, $special); case is_bool($source): - return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping, NULL, $special); + return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping, null, $special); case is_array($source) && count($source) == 1: $typename = implode('', array_keys($source)); $outtype = array_search($typename, $this->ANYmap, true); if ($outtype !== false) { - return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, NULL, $special); + return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special); } } @@ -1058,7 +1057,7 @@ class File_ASN1 { user_error('No filters defined for ' . implode('/', $loc)); return false; } - return $this->_encode_der($source, $filters + $mapping, NULL, $special); + return $this->_encode_der($source, $filters + $mapping, null, $special); case FILE_ASN1_TYPE_NULL: $value = ''; break; diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/File/X509.php b/apps/files_external/3rdparty/phpseclib/phpseclib/File/X509.php index 0b4e291361e341693ecb32e81ea824d5e9d0f01b..9e7b0b3b962445a14bff53a8a79283b728b53741 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/File/X509.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/File/X509.php @@ -1,5 +1,4 @@ - * @copyright MMXII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category File + * @package File_X509 + * @author Jim Wigginton + * @copyright MMXII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** * Include File_ASN1 */ if (!class_exists('File_ASN1')) { - require_once('ASN1.php'); + include_once 'ASN1.php'; } /** @@ -124,12 +123,13 @@ define('FILE_X509_ATTR_REPLACE', -3); // Clear first, then add a value. /** * Pure-PHP X.509 Parser * + * @package File_X509 * @author Jim Wigginton * @version 0.3.1 * @access public - * @package File_X509 */ -class File_X509 { +class File_X509 +{ /** * ASN.1 syntax for X.509 certificates * @@ -248,7 +248,7 @@ class File_X509 { * The signature subject * * There's no guarantee File_X509 is going to reencode an X.509 cert in the same way it was originally - * encoded so we take save the portion of the original cert that the signature would have made for. + * encoded so we take save the portion of the original cert that the signature would have made for. * * @var String * @access private @@ -307,7 +307,7 @@ class File_X509 { function File_X509() { if (!class_exists('Math_BigInteger')) { - require_once('Math/BigInteger.php'); + include_once 'Math/BigInteger.php'; } // Explicitly Tagged Module, 1988 Syntax @@ -1431,7 +1431,7 @@ class File_X509 { $this->currentCert = $cert; $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); - $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : NULL; + $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; unset($this->signatureSubject); @@ -1469,7 +1469,7 @@ class File_X509 { $this->dn = $x509['tbsCertificate']['subject']; $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier'); - $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : NULL; + $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null; return $x509; } @@ -1496,33 +1496,33 @@ class File_X509 { default: switch ($algorithm) { case 'rsaEncryption': - $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] = - base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']))); + $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] + = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']))); } } $asn1 = new File_ASN1(); - $asn1->loadOIDs($this->oids); $filters = array(); - $filters['tbsCertificate']['signature']['parameters'] = - $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = - $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = - $filters['tbsCertificate']['subject']['rdnSequence']['value'] = - $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = - $filters['signatureAlgorithm']['parameters'] = - $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = - //$filters['policyQualifiers']['qualifier'] = - $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = - $filters['directoryName']['rdnSequence']['value'] = - array('type' => FILE_ASN1_TYPE_UTF8_STRING); + $type_utf8_string = array('type' => FILE_ASN1_TYPE_UTF8_STRING); + $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string; + $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string; + $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string; + $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string; + $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string; + $filters['signatureAlgorithm']['parameters'] = $type_utf8_string; + $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string; + //$filters['policyQualifiers']['qualifier'] = $type_utf8_string; + $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string; + $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string; + /* in the case of policyQualifiers/qualifier, the type has to be FILE_ASN1_TYPE_IA5_STRING. FILE_ASN1_TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random characters. */ - $filters['policyQualifiers']['qualifier'] = - array('type' => FILE_ASN1_TYPE_IA5_STRING); + $filters['policyQualifiers']['qualifier'] + = array('type' => FILE_ASN1_TYPE_IA5_STRING); $asn1->loadFilters($filters); @@ -1715,8 +1715,7 @@ class File_X509 { if ($map === false) { user_error($id . ' is not a currently supported attribute', E_USER_NOTICE); unset($attributes[$i]); - } - elseif (is_array($attributes[$i]['value'])) { + } elseif (is_array($attributes[$i]['value'])) { $values = &$attributes[$i]['value']; for ($j = 0; $j < count($values); $j++) { switch ($id) { @@ -1963,7 +1962,7 @@ class File_X509 { * @param Integer $date optional * @access public */ - function validateDate($date = NULL) + function validateDate($date = null) { if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) { return false; @@ -1992,7 +1991,7 @@ class File_X509 { * Validate a signature * * Works on X.509 certs, CSR's and CRL's. - * Returns true if the signature is verified, false if it is not correct or NULL on error + * Returns true if the signature is verified, false if it is not correct or null on error * * By default returns false for self-signed certs. Call validateSignature(false) to make this support * self-signed. @@ -2006,7 +2005,7 @@ class File_X509 { function validateSignature($caonly = true) { if (!is_array($this->currentCert) || !isset($this->signatureSubject)) { - return NULL; + return null; } /* TODO: @@ -2107,7 +2106,7 @@ class File_X509 { /** * Validates a signature * - * Returns true if the signature is verified, false if it is not correct or NULL on error + * Returns true if the signature is verified, false if it is not correct or null on error * * @param String $publicKeyAlgorithm * @param String $publicKey @@ -2122,7 +2121,7 @@ class File_X509 { switch ($publicKeyAlgorithm) { case 'rsaEncryption': if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $rsa = new Crypt_RSA(); $rsa->loadKey($publicKey); @@ -2142,11 +2141,11 @@ class File_X509 { } break; default: - return NULL; + return null; } break; default: - return NULL; + return null; } return true; @@ -2367,7 +2366,7 @@ class File_X509 { * @return Mixed * @access public */ - function getDNProp($propName, $dn = NULL, $withType = false) + function getDNProp($propName, $dn = null, $withType = false) { if (!isset($dn)) { $dn = $this->dn; @@ -2421,7 +2420,7 @@ class File_X509 { function setDN($dn, $merge = false, $type = 'utf8String') { if (!$merge) { - $this->dn = NULL; + $this->dn = null; } if (is_array($dn)) { @@ -2460,7 +2459,7 @@ class File_X509 { * @access public * @return Boolean */ - function getDN($format = FILE_X509_DN_ARRAY, $dn = NULL) + function getDN($format = FILE_X509_DN_ARRAY, $dn = null) { if (!isset($dn)) { $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn; @@ -2524,7 +2523,7 @@ class File_X509 { case FILE_X509_DN_HASH: $dn = $this->getDN(FILE_X509_DN_CANON, $dn); if (!class_exists('Crypt_Hash')) { - require_once('Crypt/Hash.php'); + include_once 'Crypt/Hash.php'; } $hash = new Crypt_Hash('sha1'); $hash = $hash->hash($dn); @@ -2676,7 +2675,7 @@ class File_X509 { { switch (true) { case !empty($this->dn): - return $this->getDNProp($propName, NULL, $withType); + return $this->getDNProp($propName, null, $withType); case !isset($this->currentCert) || !is_array($this->currentCert): break; case isset($this->currentCert['tbsCertificate']): @@ -2792,7 +2791,7 @@ class File_X509 { switch ($keyinfo['algorithm']['algorithm']) { case 'rsaEncryption': if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $publicKey = new Crypt_RSA(); $publicKey->loadKey($key); @@ -2865,17 +2864,17 @@ class File_X509 { switch ($algorithm) { case 'rsaEncryption': if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $this->publicKey = new Crypt_RSA(); $this->publicKey->loadKey($key); $this->publicKey->setPublicKey(); break; default: - $this->publicKey = NULL; + $this->publicKey = null; } - $this->currentKeyIdentifier = NULL; + $this->currentKeyIdentifier = null; $this->currentCert = $csr; return $csr; @@ -2902,8 +2901,8 @@ class File_X509 { default: switch ($algorithm) { case 'rsaEncryption': - $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] = - base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']))); + $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] + = base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']))); } } @@ -2912,8 +2911,8 @@ class File_X509 { $asn1->loadOIDs($this->oids); $filters = array(); - $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] = - array('type' => FILE_ASN1_TYPE_UTF8_STRING); + $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] + = array('type' => FILE_ASN1_TYPE_UTF8_STRING); $asn1->loadFilters($filters); @@ -2990,17 +2989,17 @@ class File_X509 { switch ($algorithm) { case 'rsaEncryption': if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $this->publicKey = new Crypt_RSA(); $this->publicKey->loadKey($key); $this->publicKey->setPublicKey(); break; default: - $this->publicKey = NULL; + $this->publicKey = null; } - $this->currentKeyIdentifier = NULL; + $this->currentKeyIdentifier = null; $this->currentCert = $spkac; return $spkac; @@ -3048,14 +3047,14 @@ class File_X509 { $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); $this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1); - $rclist = &$this->_subArray($crl,'tbsCertList/revokedCertificates'); + $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates'); if (is_array($rclist)) { foreach ($rclist as $i => $extension) { $this->_mapInExtensions($rclist, "$i/crlEntryExtensions", $asn1); } } - $this->currentKeyIdentifier = NULL; + $this->currentKeyIdentifier = null; $this->currentCert = $crl; return $crl; @@ -3080,25 +3079,27 @@ class File_X509 { $asn1->loadOIDs($this->oids); $filters = array(); - $filters['tbsCertList']['issuer']['rdnSequence']['value'] = - $filters['tbsCertList']['signature']['parameters'] = - $filters['signatureAlgorithm']['parameters'] = - array('type' => FILE_ASN1_TYPE_UTF8_STRING); + $filters['tbsCertList']['issuer']['rdnSequence']['value'] + = array('type' => FILE_ASN1_TYPE_UTF8_STRING); + $filters['tbsCertList']['signature']['parameters'] + = array('type' => FILE_ASN1_TYPE_UTF8_STRING); + $filters['signatureAlgorithm']['parameters'] + = array('type' => FILE_ASN1_TYPE_UTF8_STRING); if (empty($crl['tbsCertList']['signature']['parameters'])) { - $filters['tbsCertList']['signature']['parameters'] = - array('type' => FILE_ASN1_TYPE_NULL); + $filters['tbsCertList']['signature']['parameters'] + = array('type' => FILE_ASN1_TYPE_NULL); } if (empty($crl['signatureAlgorithm']['parameters'])) { - $filters['signatureAlgorithm']['parameters'] = - array('type' => FILE_ASN1_TYPE_NULL); + $filters['signatureAlgorithm']['parameters'] + = array('type' => FILE_ASN1_TYPE_NULL); } $asn1->loadFilters($filters); $this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1); - $rclist = &$this->_subArray($crl,'tbsCertList/revokedCertificates'); + $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates'); if (is_array($rclist)) { foreach ($rclist as $i => $extension) { $this->_mapOutExtensions($rclist, "$i/crlEntryExtensions", $asn1); @@ -3139,14 +3140,14 @@ class File_X509 { return false; } - $currentCert = isset($this->currentCert) ? $this->currentCert : NULL; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: NULL; + $currentCert = isset($this->currentCert) ? $this->currentCert : null; + $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) { $this->currentCert = $subject->currentCert; - $this->currentCert['tbsCertificate']['signature']['algorithm'] = - $this->currentCert['signatureAlgorithm']['algorithm'] = - $signatureAlgorithm; + $this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm; + $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; + if (!empty($this->startDate)) { $this->currentCert['tbsCertificate']['validity']['notBefore']['generalTime'] = $this->startDate; unset($this->currentCert['tbsCertificate']['validity']['notBefore']['utcTime']); @@ -3312,12 +3313,11 @@ class File_X509 { } $this->publicKey = $origPublicKey; - $currentCert = isset($this->currentCert) ? $this->currentCert : NULL; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: NULL; + $currentCert = isset($this->currentCert) ? $this->currentCert : null; + $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null; if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) { - $this->currentCert['signatureAlgorithm']['algorithm'] = - $signatureAlgorithm; + $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm; if (!empty($this->dn)) { $this->currentCert['certificationRequestInfo']['subject'] = $this->dn; } @@ -3366,8 +3366,8 @@ class File_X509 { return false; } - $currentCert = isset($this->currentCert) ? $this->currentCert : NULL; - $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : NULL; + $currentCert = isset($this->currentCert) ? $this->currentCert : null; + $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null; $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O'); if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { @@ -3400,10 +3400,9 @@ class File_X509 { if (!empty($this->serialNumber)) { $crlNumber = $this->serialNumber; - } - else { + } else { $crlNumber = $this->getExtension('id-ce-cRLNumber'); - $crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : NULL; + $crlNumber = $crlNumber !== false ? $crlNumber->add(new Math_BigInteger(1)) : null; } $this->removeExtension('id-ce-authorityKeyIdentifier'); @@ -3414,8 +3413,7 @@ class File_X509 { if (!$version) { if (!empty($tbsCertList['crlExtensions'])) { $version = 1; // v2. - } - elseif (!empty($tbsCertList['revokedCertificates'])) { + } elseif (!empty($tbsCertList['revokedCertificates'])) { foreach ($tbsCertList['revokedCertificates'] as $cert) { if (!empty($cert['crlEntryExtensions'])) { $version = 1; // v2. @@ -3613,7 +3611,7 @@ class File_X509 { * @access private * @return array ref or false */ - function &_extensions(&$root, $path = NULL, $create = false) + function &_extensions(&$root, $path = null, $create = false) { if (!isset($root)) { $root = $this->currentCert; @@ -3667,7 +3665,7 @@ class File_X509 { * @access private * @return Boolean */ - function _removeExtension($id, $path = NULL) + function _removeExtension($id, $path = null) { $extensions = &$this->_extensions($this->currentCert, $path); @@ -3698,7 +3696,7 @@ class File_X509 { * @access private * @return Mixed */ - function _getExtension($id, $cert = NULL, $path = NULL) + function _getExtension($id, $cert = null, $path = null) { $extensions = $this->_extensions($cert, $path); @@ -3723,7 +3721,7 @@ class File_X509 { * @access private * @return Array */ - function _getExtensions($cert = NULL, $path = NULL) + function _getExtensions($cert = null, $path = null) { $exts = $this->_extensions($cert, $path); $extensions = array(); @@ -3748,7 +3746,7 @@ class File_X509 { * @access private * @return Boolean */ - function _setExtension($id, $value, $critical = false, $replace = true, $path = NULL) + function _setExtension($id, $value, $critical = false, $replace = true, $path = null) { $extensions = &$this->_extensions($this->currentCert, $path, true); @@ -3795,7 +3793,7 @@ class File_X509 { * @access public * @return Mixed */ - function getExtension($id, $cert = NULL) + function getExtension($id, $cert = null) { return $this->_getExtension($id, $cert); } @@ -3807,7 +3805,7 @@ class File_X509 { * @access public * @return Array */ - function getExtensions($cert = NULL) + function getExtensions($cert = null) { return $this->_getExtensions($cert); } @@ -3886,7 +3884,7 @@ class File_X509 { * @access public * @return Mixed */ - function getAttribute($id, $disposition = FILE_X509_ATTR_ALL, $csr = NULL) + function getAttribute($id, $disposition = FILE_X509_ATTR_ALL, $csr = null) { if (empty($csr)) { $csr = $this->currentCert; @@ -3926,7 +3924,7 @@ class File_X509 { * @access public * @return Array */ - function getAttributes($csr = NULL) + function getAttributes($csr = null) { if (empty($csr)) { $csr = $this->currentCert; @@ -4035,7 +4033,7 @@ class File_X509 { * @access public * @return String binary key identifier */ - function computeKeyIdentifier($key = NULL, $method = 1) + function computeKeyIdentifier($key = null, $method = 1) { if (is_null($key)) { $key = $this; @@ -4064,7 +4062,7 @@ class File_X509 { $raw = base64_decode($raw); // If the key is private, compute identifier from its corresponding public key. if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $key = new Crypt_RSA(); if (!$key->loadKey($raw)) { @@ -4096,7 +4094,7 @@ class File_X509 { // Now we have the key string: compute its sha-1 sum. if (!class_exists('Crypt_Hash')) { - require_once('Crypt/Hash.php'); + include_once 'Crypt/Hash.php'; } $hash = new Crypt_Hash('sha1'); $hash = $hash->hash($key); @@ -4228,7 +4226,7 @@ class File_X509 { * @access public * @return Boolean */ - function revoke($serial, $date = NULL) + function revoke($serial, $date = null) { if (isset($this->currentCert['tbsCertList'])) { if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) { @@ -4293,7 +4291,7 @@ class File_X509 { * @access public * @return array */ - function listRevoked($crl = NULL) + function listRevoked($crl = null) { if (!isset($crl)) { $crl = $this->currentCert; @@ -4344,7 +4342,7 @@ class File_X509 { * @access public * @return Mixed */ - function getRevokedCertificateExtension($serial, $id, $crl = NULL) + function getRevokedCertificateExtension($serial, $id, $crl = null) { if (!isset($crl)) { $crl = $this->currentCert; @@ -4367,7 +4365,7 @@ class File_X509 { * @access public * @return Array */ - function getRevokedCertificateExtensions($serial, $crl = NULL) + function getRevokedCertificateExtensions($serial, $crl = null) { if (!isset($crl)) { $crl = $this->currentCert; @@ -4415,15 +4413,15 @@ class File_X509 { */ function _extractBER($str) { - /* - X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them above and beyond the ceritificate. ie. - some may have the following preceding the -----BEGIN CERTIFICATE----- line: - - Bag Attributes - localKeyID: 01 00 00 00 - subject=/O=organization/OU=org unit/CN=common name - issuer=/O=organization/CN=common name - */ + /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them + * above and beyond the ceritificate. + * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: + * + * Bag Attributes + * localKeyID: 01 00 00 00 + * subject=/O=organization/OU=org unit/CN=common name + * issuer=/O=organization/CN=common name + */ $temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1); // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff $temp = preg_replace('#-+[^-]+-+#', '', $temp); diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Math/BigInteger.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Math/BigInteger.php index e40433de5bd91d69a0a947b081ef7c53fc45963e..1b4ea675fcc92ba65564b238197ddb60bc059f11 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Math/BigInteger.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Math/BigInteger.php @@ -1,5 +1,4 @@ - * @copyright MMVI Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://pear.php.net/package/Math_BigInteger + * @category Math + * @package Math_BigInteger + * @author Jim Wigginton + * @copyright MMVI Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://pear.php.net/package/Math_BigInteger */ /**#@+ @@ -174,12 +173,13 @@ define('MATH_BIGINTEGER_KARATSUBA_CUTOFF', 25); * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256 * numbers. * + * @package Math_BigInteger * @author Jim Wigginton * @version 1.0.0RC4 * @access public - * @package Math_BigInteger */ -class Math_BigInteger { +class Math_BigInteger +{ /** * Holds the BigInteger's value. * @@ -223,7 +223,7 @@ class Math_BigInteger { /** * Mode independent value used for serialization. * - * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for + * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value, * however, $this->hex is only calculated when $this->__sleep() is called. * @@ -797,7 +797,7 @@ class Math_BigInteger { $vars[] = 'precision'; } return $vars; - + } /** @@ -2279,7 +2279,7 @@ class Math_BigInteger { /** * Montgomery Multiply * - * Interleaves the montgomery reduction and long multiplication algorithms together as described in + * Interleaves the montgomery reduction and long multiplication algorithms together as described in * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} * * @see _prepMontgomery() @@ -2359,7 +2359,7 @@ class Math_BigInteger { * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85} * * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For - * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields + * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the @@ -3290,7 +3290,7 @@ class Math_BigInteger { * @return Boolean * @access public * @internal Uses the - * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See + * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24}. */ function isPrime($t = false) @@ -3299,6 +3299,7 @@ class Math_BigInteger { if (!$t) { // see HAC 4.49 "Note (controlling the error probability)" + // @codingStandardsIgnoreStart if ($length >= 163) { $t = 2; } // floor(1300 / 8) else if ($length >= 106) { $t = 3; } // floor( 850 / 8) else if ($length >= 81 ) { $t = 4; } // floor( 650 / 8) @@ -3311,6 +3312,7 @@ class Math_BigInteger { else if ($length >= 25 ) { $t = 15; } // floor( 200 / 8) else if ($length >= 18 ) { $t = 18; } // floor( 150 / 8) else { $t = 27; } + // @codingStandardsIgnoreEnd } // ie. gmp_testbit($this, 0) @@ -3339,16 +3341,16 @@ class Math_BigInteger { if (!isset($primes)) { $primes = array( - 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, + 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 ); diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SCP.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SCP.php index 88180cac67a6baa3461a346866dcd024e494add0..4cfa357009f50972f1a027592f9702173fd63dc0 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SCP.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SCP.php @@ -1,5 +1,4 @@ - * @copyright MMX Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Net + * @package Net_SCP + * @author Jim Wigginton + * @copyright MMX Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /**#@+ @@ -82,12 +81,13 @@ define('NET_SCP_SSH2', 2); /** * Pure-PHP implementations of SCP. * + * @package Net_SCP * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Net_SCP */ -class Net_SCP { +class Net_SCP +{ /** * SSH Object * @@ -151,7 +151,7 @@ class Net_SCP { * So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes * long, containing 'filename.ext' as its contents. * - * Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will + * Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how * large $remote_file will be, as well. * @@ -181,7 +181,7 @@ class Net_SCP { } if ($this->mode == NET_SCP_SSH2) { - $this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC]; + $this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC] - 4; } $remote_file = basename($remote_file); @@ -353,7 +353,7 @@ class Net_SCP { { switch ($this->mode) { case NET_SCP_SSH2: - $this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC); + $this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC, true); break; case NET_SCP_SSH1: $this->ssh->disconnect(); diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP.php index 5356ffbf77ab6370e059c4751a3aab434d3ddb9a..68d944f9f3f5ad91a51008cf4e5eeee7adab83c3 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP.php @@ -1,5 +1,4 @@ - * @copyright MMIX Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Net + * @package Net_SFTP + * @author Jim Wigginton + * @copyright MMIX Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** * Include Net_SSH2 */ if (!class_exists('Net_SSH2')) { - require_once('SSH2.php'); + include_once 'SSH2.php'; } /**#@+ @@ -116,12 +115,13 @@ define('NET_SFTP_RESUME_START', 8); /** * Pure-PHP implementations of SFTP. * + * @package Net_SFTP * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Net_SFTP */ -class Net_SFTP extends Net_SSH2 { +class Net_SFTP extends Net_SSH2 +{ /** * Packet Types * @@ -233,7 +233,7 @@ class Net_SFTP extends Net_SSH2 { * Directory Cache * * Rather than always having to open a directory and close it immediately there after to see if a file is a directory or - * rather than always + * rather than always * * @see Net_SFTP::_save_dir() * @see Net_SFTP::_remove_dir() @@ -347,7 +347,7 @@ class Net_SFTP extends Net_SSH2 { 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS', 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME', // 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers - // yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in + // yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in // two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000. // that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored. -1 << 31 => 'NET_SFTP_ATTR_EXTENDED' @@ -402,7 +402,7 @@ class Net_SFTP extends Net_SSH2 { function login($username) { $args = func_get_args(); - if (!call_user_func_array(array('Net_SSH2', 'login'), $args)) { + if (!call_user_func_array(array(&$this, '_login'), $args)) { return false; } @@ -635,7 +635,11 @@ class Net_SFTP extends Net_SSH2 { return false; } - if ($dir[strlen($dir) - 1] != '/') { + // assume current dir if $dir is empty + if ($dir === '') { + $dir = './'; + // suffix a slash if needed + } elseif ($dir[strlen($dir) - 1] != '/') { $dir.= '/'; } @@ -1038,7 +1042,7 @@ class Net_SFTP extends Net_SSH2 { */ function truncate($filename, $new_size) { - $attr = pack('N3', NET_SFTP_ATTR_SIZE, $new_size / 0x100000000, $new_size); + $attr = pack('N3', NET_SFTP_ATTR_SIZE, $new_size / 4294967296, $new_size); // 4294967296 == 0x100000000 == 1<<32 return $this->_setstat($filename, $attr, false); } @@ -1054,7 +1058,7 @@ class Net_SFTP extends Net_SSH2 { * @return Boolean * @access public */ - function touch($filename, $time = NULL, $atime = NULL) + function touch($filename, $time = null, $atime = null) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { return false; @@ -1097,7 +1101,7 @@ class Net_SFTP extends Net_SSH2 { /** * Changes file or directory owner * - * Returns TRUE on success or FALSE on error. + * Returns true on success or false on error. * * @param String $filename * @param Integer $uid @@ -1117,7 +1121,7 @@ class Net_SFTP extends Net_SSH2 { /** * Changes file or directory group * - * Returns TRUE on success or FALSE on error. + * Returns true on success or false on error. * * @param String $filename * @param Integer $gid @@ -1135,8 +1139,8 @@ class Net_SFTP extends Net_SSH2 { /** * Set permissions on a file. * - * Returns the new file permissions on success or FALSE on error. - * If $recursive is true than this just returns TRUE or FALSE. + * Returns the new file permissions on success or false on error. + * If $recursive is true than this just returns true or false. * * @param Integer $mode * @param String $filename @@ -1216,7 +1220,7 @@ class Net_SFTP extends Net_SSH2 { } /* - "Because some systems must use separate system calls to set various attributes, it is possible that a failure + "Because some systems must use separate system calls to set various attributes, it is possible that a failure response will be returned, but yet some of the attributes may be have been successfully modified. If possible, servers SHOULD avoid this situation; however, clients MUST be aware that this is possible." @@ -1326,7 +1330,7 @@ class Net_SFTP extends Net_SSH2 { } $dir = $this->_realpath($dir); - // by not providing any permissions, hopefully the server will use the logged in users umask - their + // by not providing any permissions, hopefully the server will use the logged in users umask - their // default permissions. $attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777); @@ -1424,7 +1428,7 @@ class Net_SFTP extends Net_SSH2 { * So, for example, if you set $data to 'filename.ext' and then do Net_SFTP::get(), you will get a file, twelve bytes * long, containing 'filename.ext' as its contents. * - * Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will + * Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how * large $remote_file will be, as well. * @@ -1502,8 +1506,6 @@ class Net_SFTP extends Net_SSH2 { return false; } - $initialize = true; - // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3 if ($mode & NET_SFTP_LOCAL_FILE) { if (!is_file($data)) { @@ -1537,7 +1539,7 @@ class Net_SFTP extends Net_SSH2 { while ($sent < $size) { $temp = $mode & NET_SFTP_LOCAL_FILE ? fread($fp, $sftp_packet_size) : substr($data, $sent, $sftp_packet_size); $subtemp = $offset + $sent; - $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 0x100000000, $subtemp, strlen($temp), $temp); + $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp); if (!$this->_send_sftp_packet(NET_SFTP_WRITE, $packet)) { fclose($fp); return false; @@ -1683,9 +1685,10 @@ class Net_SFTP extends Net_SSH2 { $content = ''; } + $start = $offset; $size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length; while (true) { - $packet = pack('Na*N3', strlen($handle), $handle, $offset / 0x100000000, $offset, $size); + $packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size); if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) { if ($local_file !== false) { fclose($fp); @@ -1716,12 +1719,12 @@ class Net_SFTP extends Net_SSH2 { return false; } - if ($length > 0 && $length <= $offset - $size) { + if ($length > 0 && $length <= $offset - $start) { break; } } - if ($length > 0 && $length <= $offset - $size) { + if ($length > 0 && $length <= $offset - $start) { if ($local_file === false) { $content = substr($content, 0, $length); } else { @@ -1923,7 +1926,7 @@ class Net_SFTP extends Net_SSH2 { // (0xFFFFFFFF bytes), anyway. as such, we'll just represent all file sizes that are bigger than // 4GB as being 4GB. extract(unpack('Nupper/Nsize', $this->_string_shift($response, 8))); - $attr['size'] = $upper ? 0x100000000 * $upper : 0; + $attr['size'] = $upper ? 4294967296 * $upper : 0; $attr['size']+= $size < 0 ? ($size & 0x7FFFFFFF) + 0x80000000 : $size; break; case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only) @@ -2054,7 +2057,7 @@ class Net_SFTP extends Net_SSH2 { $stop = strtok(microtime(), ' ') + strtok(''); if (defined('NET_SFTP_LOGGING')) { - $packet_type = '-> ' . $this->packet_types[$type] . + $packet_type = '-> ' . $this->packet_types[$type] . ' (' . round($stop - $start, 4) . 's)'; if (NET_SFTP_LOGGING == NET_SFTP_LOG_REALTIME) { echo "
\r\n" . $this->_format_log(array($data), array($packet_type)) . "\r\n
\r\n"; @@ -2130,7 +2133,7 @@ class Net_SFTP extends Net_SSH2 { $packet = $this->_string_shift($this->packet_buffer, $length); if (defined('NET_SFTP_LOGGING')) { - $packet_type = '<- ' . $this->packet_types[$this->packet_type] . + $packet_type = '<- ' . $this->packet_types[$this->packet_type] . ' (' . round($stop - $start, 4) . 's)'; if (NET_SFTP_LOGGING == NET_SFTP_LOG_REALTIME) { echo "
\r\n" . $this->_format_log(array($packet), array($packet_type)) . "\r\n
\r\n"; diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP/Stream.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP/Stream.php index 0572c5c4025b55d6bf58a74c879f3987d01ff56a..48b79b3ef7f55eb1d4b37d0ff3dd00ce5bbc4145 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP/Stream.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SFTP/Stream.php @@ -1,5 +1,4 @@ - * @copyright MMXIII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Net + * @package Net_SFTP_Stream + * @author Jim Wigginton + * @copyright MMXIII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /** * SFTP Stream Wrapper * + * @package Net_SFTP_Stream * @author Jim Wigginton * @version 0.3.2 * @access public - * @package Net_SFTP_Stream */ -class Net_SFTP_Stream { +class Net_SFTP_Stream +{ /** * SFTP instances * @@ -134,8 +134,12 @@ class Net_SFTP_Stream { */ function Net_SFTP_Stream() { + if (defined('NET_SFTP_STREAM_LOGGING')) { + echo "__construct()\r\n"; + } + if (!class_exists('Net_SFTP')) { - require_once('Net/SFTP.php'); + include_once 'Net/SFTP.php'; } } @@ -513,7 +517,7 @@ class Net_SFTP_Stream { * Open directory handle * * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and - * removed in 5.4 I'm just going to ignore it + * removed in 5.4 I'm just going to ignore it * * @param String $path * @param Integer $options diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH1.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH1.php index 83d5980d00acf962575c23caf6225d1c92258ee8..0a6aa90828958f462f6349c588172497e9532bf0 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH1.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH1.php @@ -1,5 +1,4 @@ * * - * More information on the SSHv1 specification can be found by reading + * More information on the SSHv1 specification can be found by reading * {@link http://www.snailbook.com/docs/protocol-1.5.txt protocol-1.5.txt}. * * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy @@ -45,10 +44,10 @@ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -57,12 +56,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * - * @category Net - * @package Net_SSH1 - * @author Jim Wigginton - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Net + * @package Net_SSH1 + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /**#@+ @@ -202,11 +201,11 @@ define('NET_SSH1_LOG_COMPLEX', 2); /** * Outputs the content real-time */ -define('NET_SSH2_LOG_REALTIME', 3); +define('NET_SSH1_LOG_REALTIME', 3); /** * Dumps the content real-time to a file */ -define('NET_SSH2_LOG_REALTIME_FILE', 4); +define('NET_SSH1_LOG_REALTIME_FILE', 4); /**#@-*/ /**#@+ @@ -226,12 +225,13 @@ define('NET_SSH1_READ_REGEX', 2); /** * Pure-PHP implementation of SSHv1. * + * @package Net_SSH1 * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Net_SSH1 */ -class Net_SSH1 { +class Net_SSH1 +{ /** * The SSH identifier * @@ -429,11 +429,35 @@ class Net_SSH1 { /** * Current Timeout * - * @see Net_SSH2::_get_channel_packet() + * @see Net_SSH1::_get_channel_packet() * @access private */ var $curTimeout; + /** + * Log Boundary + * + * @see Net_SSH1::_format_log + * @access private + */ + var $log_boundary = ':'; + + /** + * Log Long Width + * + * @see Net_SSH1::_format_log + * @access private + */ + var $log_long_width = 65; + + /** + * Log Short Width + * + * @see Net_SSH1::_format_log + * @access private + */ + var $log_short_width = 16; + /** * Default Constructor. * @@ -449,16 +473,16 @@ class Net_SSH1 { function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES) { if (!class_exists('Math_BigInteger')) { - require_once('Math/BigInteger.php'); + include_once 'Math/BigInteger.php'; } // Include Crypt_Random // the class_exists() will only be called if the crypt_random_string function hasn't been defined and // will trigger a call to __autoload() if you're wanting to auto-load classes - // call function_exists() a second time to stop the require_once from being called outside + // call function_exists() a second time to stop the include_once from being called outside // of the auto loader if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) { - require_once('Crypt/Random.php'); + include_once 'Crypt/Random.php'; } $this->protocol_flags = array( @@ -603,7 +627,7 @@ class Net_SSH1 { // break; case NET_SSH1_CIPHER_DES: if (!class_exists('Crypt_DES')) { - require_once('Crypt/DES.php'); + include_once 'Crypt/DES.php'; } $this->crypto = new Crypt_DES(); $this->crypto->disablePadding(); @@ -612,7 +636,7 @@ class Net_SSH1 { break; case NET_SSH1_CIPHER_3DES: if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC); $this->crypto->disablePadding(); @@ -621,7 +645,7 @@ class Net_SSH1 { break; //case NET_SSH1_CIPHER_RC4: // if (!class_exists('Crypt_RC4')) { - // require_once('Crypt/RC4.php'); + // include_once('Crypt/RC4.php'); // } // $this->crypto = new Crypt_RC4(); // $this->crypto->enableContinuousBuffer(); @@ -1017,7 +1041,7 @@ class Net_SSH1 { if ($this->curTimeout) { $read = array($this->fsock); - $write = $except = NULL; + $write = $except = null; $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $sec = floor($this->curTimeout); @@ -1253,7 +1277,7 @@ class Net_SSH1 { { /* if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $rsa = new Crypt_RSA(); @@ -1318,7 +1342,7 @@ class Net_SSH1 { /** * Returns a log of the packets that have been sent and received. * - * Returns a string if NET_SSH2_LOGGING == NET_SSH2_LOG_COMPLEX, an array if NET_SSH2_LOGGING == NET_SSH2_LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING') + * Returns a string if NET_SSH1_LOGGING == NET_SSH1_LOG_COMPLEX, an array if NET_SSH1_LOGGING == NET_SSH1_LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING') * * @access public * @return String or Array @@ -1351,8 +1375,6 @@ class Net_SSH1 { */ function _format_log($message_log, $message_number_log) { - static $boundary = ':', $long_width = 65, $short_width = 16; - $output = ''; for ($i = 0; $i < count($message_log); $i++) { $output.= $message_number_log[$i] . "\r\n"; @@ -1362,19 +1384,13 @@ class Net_SSH1 { if (strlen($current_log)) { $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; } - $fragment = $this->_string_shift($current_log, $short_width); - $hex = substr( - preg_replace( - '#(.)#es', - '"' . $boundary . '" . str_pad(dechex(ord(substr("\\1", -1))), 2, "0", STR_PAD_LEFT)', - $fragment), - strlen($boundary) - ); + $fragment = $this->_string_shift($current_log, $this->log_short_width); + $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary)); // replace non ASCII printable characters with dots // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters // also replace < with a . since < messes up the output on web browsers $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); - $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n"; + $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n"; $j++; } while (strlen($current_log)); $output.= "\r\n"; @@ -1383,6 +1399,20 @@ class Net_SSH1 { return $output; } + /** + * Helper function for _format_log + * + * For use with preg_replace_callback() + * + * @param Array $matches + * @access private + * @return String + */ + function _format_log_helper($matches) + { + return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT); + } + /** * Return the server key public exponent * @@ -1496,57 +1526,57 @@ class Net_SSH1 { */ function _append_log($protocol_flags, $message) { - switch (NET_SSH1_LOGGING) { - // useful for benchmarks - case NET_SSH1_LOG_SIMPLE: - $this->protocol_flags_log[] = $protocol_flags; - break; - // the most useful log for SSH1 - case NET_SSH1_LOG_COMPLEX: - $this->protocol_flags_log[] = $protocol_flags; - $this->_string_shift($message); - $this->log_size+= strlen($message); - $this->message_log[] = $message; - while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) { - $this->log_size-= strlen(array_shift($this->message_log)); - array_shift($this->protocol_flags_log); - } - break; - // dump the output out realtime; packets may be interspersed with non packets, - // passwords won't be filtered out and select other packets may not be correctly - // identified - case NET_SSH1_LOG_REALTIME: - echo "
\r\n" . $this->_format_log(array($message), array($protocol_flags)) . "\r\n
\r\n"; - @flush(); - @ob_flush(); + switch (NET_SSH1_LOGGING) { + // useful for benchmarks + case NET_SSH1_LOG_SIMPLE: + $this->protocol_flags_log[] = $protocol_flags; + break; + // the most useful log for SSH1 + case NET_SSH1_LOG_COMPLEX: + $this->protocol_flags_log[] = $protocol_flags; + $this->_string_shift($message); + $this->log_size+= strlen($message); + $this->message_log[] = $message; + while ($this->log_size > NET_SSH1_LOG_MAX_SIZE) { + $this->log_size-= strlen(array_shift($this->message_log)); + array_shift($this->protocol_flags_log); + } + break; + // dump the output out realtime; packets may be interspersed with non packets, + // passwords won't be filtered out and select other packets may not be correctly + // identified + case NET_SSH1_LOG_REALTIME: + echo "
\r\n" . $this->_format_log(array($message), array($protocol_flags)) . "\r\n
\r\n"; + @flush(); + @ob_flush(); + break; + // basically the same thing as NET_SSH1_LOG_REALTIME with the caveat that NET_SSH1_LOG_REALTIME_FILE + // needs to be defined and that the resultant log file will be capped out at NET_SSH1_LOG_MAX_SIZE. + // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily + // at the beginning of the file + case NET_SSH1_LOG_REALTIME_FILE: + if (!isset($this->realtime_log_file)) { + // PHP doesn't seem to like using constants in fopen() + $filename = NET_SSH1_LOG_REALTIME_FILE; + $fp = fopen($filename, 'w'); + $this->realtime_log_file = $fp; + } + if (!is_resource($this->realtime_log_file)) { break; - // basically the same thing as NET_SSH1_LOG_REALTIME with the caveat that NET_SSH1_LOG_REALTIME_FILE - // needs to be defined and that the resultant log file will be capped out at NET_SSH1_LOG_MAX_SIZE. - // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily - // at the beginning of the file - case NET_SSH1_LOG_REALTIME_FILE: - if (!isset($this->realtime_log_file)) { - // PHP doesn't seem to like using constants in fopen() - $filename = NET_SSH2_LOG_REALTIME_FILE; - $fp = fopen($filename, 'w'); - $this->realtime_log_file = $fp; - } - if (!is_resource($this->realtime_log_file)) { - break; - } - $entry = $this->_format_log(array($message), array($protocol_flags)); - if ($this->realtime_log_wrap) { - $temp = "<<< START >>>\r\n"; - $entry.= $temp; - fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); - } - $this->realtime_log_size+= strlen($entry); - if ($this->realtime_log_size > NET_SSH1_LOG_MAX_SIZE) { - fseek($this->realtime_log_file, 0); - $this->realtime_log_size = strlen($entry); - $this->realtime_log_wrap = true; - } - fputs($this->realtime_log_file, $entry); - } + } + $entry = $this->_format_log(array($message), array($protocol_flags)); + if ($this->realtime_log_wrap) { + $temp = "<<< START >>>\r\n"; + $entry.= $temp; + fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); + } + $this->realtime_log_size+= strlen($entry); + if ($this->realtime_log_size > NET_SSH1_LOG_MAX_SIZE) { + fseek($this->realtime_log_file, 0); + $this->realtime_log_size = strlen($entry); + $this->realtime_log_wrap = true; + } + fputs($this->realtime_log_file, $entry); + } } } diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH2.php b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH2.php index dad03697233d746ecf4735f9dba44077b8095c1f..2fddb68a9b2fd9cfde0f12208badabe35fa76592 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH2.php +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/Net/SSH2.php @@ -1,5 +1,4 @@ - * @copyright MMVII Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net + * @category Net + * @package Net_SSH2 + * @author Jim Wigginton + * @copyright MMVII Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net */ /**#@+ @@ -144,19 +143,20 @@ define('NET_SSH2_LOG_MAX_SIZE', 1024 * 1024); /** * Pure-PHP implementation of SSHv2. * + * @package Net_SSH2 * @author Jim Wigginton * @version 0.1.0 * @access public - * @package Net_SSH2 */ -class Net_SSH2 { +class Net_SSH2 +{ /** * The SSH identifier * * @var String * @access private */ - var $identifier = 'SSH-2.0-phpseclib_0.3'; + var $identifier; /** * The Socket Object @@ -747,6 +747,30 @@ class Net_SSH2 { */ var $is_timeout = false; + /** + * Log Boundary + * + * @see Net_SSH2::_format_log + * @access private + */ + var $log_boundary = ':'; + + /** + * Log Long Width + * + * @see Net_SSH2::_format_log + * @access private + */ + var $log_long_width = 65; + + /** + * Log Short Width + * + * @see Net_SSH2::_format_log + * @access private + */ + var $log_short_width = 16; + /** * Default Constructor. * @@ -763,15 +787,15 @@ class Net_SSH2 { // Include Math_BigInteger // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification. if (!class_exists('Math_BigInteger')) { - require_once('Math/BigInteger.php'); + include_once 'Math/BigInteger.php'; } if (!function_exists('crypt_random_string')) { - require_once('Crypt/Random.php'); + include_once 'Crypt/Random.php'; } if (!class_exists('Crypt_Hash')) { - require_once('Crypt/Hash.php'); + include_once 'Crypt/Hash.php'; } $this->last_packet = strtok(microtime(), ' ') + strtok(''); // == microtime(true) in PHP5 @@ -861,7 +885,7 @@ class Net_SSH2 { } $read = array($this->fsock); - $write = $except = NULL; + $write = $except = null; $sec = floor($timeout); $usec = 1000000 * ($timeout - $sec); @@ -895,19 +919,7 @@ class Net_SSH2 { return false; } - $ext = array(); - if (extension_loaded('mcrypt')) { - $ext[] = 'mcrypt'; - } - if (extension_loaded('gmp')) { - $ext[] = 'gmp'; - } else if (extension_loaded('bcmath')) { - $ext[] = 'bcmath'; - } - - if (!empty($ext)) { - $this->identifier.= ' (' . implode(', ', $ext) . ')'; - } + $this->identifier = $this->_generate_identifier(); if (defined('NET_SSH2_LOGGING')) { $this->_append_log('<-', $extra . $temp); @@ -944,6 +956,36 @@ class Net_SSH2 { $this->bitmap = NET_SSH2_MASK_CONSTRUCTOR; } + /** + * Generates the SSH identifier + * + * You should overwrite this method in your own class if you want to use another identifier + * + * @access protected + * @return String + */ + function _generate_identifier() + { + $identifier = 'SSH-2.0-phpseclib_0.3'; + + $ext = array(); + if (extension_loaded('mcrypt')) { + $ext[] = 'mcrypt'; + } + + if (extension_loaded('gmp')) { + $ext[] = 'gmp'; + } elseif (extension_loaded('bcmath')) { + $ext[] = 'bcmath'; + } + + if (!empty($ext)) { + $identifier .= ' (' . implode(', ', $ext) . ')'; + } + + return $identifier; + } + /** * Key Exchange * @@ -1223,23 +1265,23 @@ class Net_SSH2 { } switch ($kex_algorithms[$i]) { - // see http://tools.ietf.org/html/rfc2409#section-6.2 and + // see http://tools.ietf.org/html/rfc2409#section-6.2 and // http://tools.ietf.org/html/rfc2412, appendex E case 'diffie-hellman-group1-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . + $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . + '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . + '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF'; break; // see http://tools.ietf.org/html/rfc3526#section-3 case 'diffie-hellman-group14-sha1': - $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . - '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . - '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . - 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . - '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . - '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . - 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . + $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' . + '020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437' . + '4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED' . + 'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05' . + '98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB' . + '9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B' . + 'E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718' . '3995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF'; break; } @@ -1260,7 +1302,8 @@ class Net_SSH2 { -- http://tools.ietf.org/html/rfc4419#section-6.2 */ $one = new Math_BigInteger(1); $keyLength = min($keyLength, $kexHash->getLength()); - $max = $one->bitwise_leftShift(16 * $keyLength)->subtract($one); // 2 * 8 * $keyLength + $max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength + $max = $max->subtract($one); $x = $one->random($one, $max); $e = $g->modPow($x, $prime); @@ -1353,14 +1396,14 @@ class Net_SSH2 { switch ($encrypt) { case '3des-cbc': if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $this->encrypt = new Crypt_TripleDES(); // $this->encrypt_block_size = 64 / 8 == the default break; case '3des-ctr': if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $this->encrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); // $this->encrypt_block_size = 64 / 8 == the default @@ -1369,7 +1412,7 @@ class Net_SSH2 { case 'aes192-cbc': case 'aes128-cbc': if (!class_exists('Crypt_Rijndael')) { - require_once('Crypt/Rijndael.php'); + include_once 'Crypt/Rijndael.php'; } $this->encrypt = new Crypt_Rijndael(); $this->encrypt_block_size = 16; // eg. 128 / 8 @@ -1378,21 +1421,21 @@ class Net_SSH2 { case 'aes192-ctr': case 'aes128-ctr': if (!class_exists('Crypt_Rijndael')) { - require_once('Crypt/Rijndael.php'); + include_once 'Crypt/Rijndael.php'; } $this->encrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR); $this->encrypt_block_size = 16; // eg. 128 / 8 break; case 'blowfish-cbc': if (!class_exists('Crypt_Blowfish')) { - require_once('Crypt/Blowfish.php'); + include_once 'Crypt/Blowfish.php'; } $this->encrypt = new Crypt_Blowfish(); $this->encrypt_block_size = 8; break; case 'blowfish-ctr': if (!class_exists('Crypt_Blowfish')) { - require_once('Crypt/Blowfish.php'); + include_once 'Crypt/Blowfish.php'; } $this->encrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); $this->encrypt_block_size = 8; @@ -1402,7 +1445,7 @@ class Net_SSH2 { case 'twofish256-cbc': case 'twofish-cbc': if (!class_exists('Crypt_Twofish')) { - require_once('Crypt/Twofish.php'); + include_once 'Crypt/Twofish.php'; } $this->encrypt = new Crypt_Twofish(); $this->encrypt_block_size = 16; @@ -1411,7 +1454,7 @@ class Net_SSH2 { case 'twofish192-ctr': case 'twofish256-ctr': if (!class_exists('Crypt_Twofish')) { - require_once('Crypt/Twofish.php'); + include_once 'Crypt/Twofish.php'; } $this->encrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); $this->encrypt_block_size = 16; @@ -1420,7 +1463,7 @@ class Net_SSH2 { case 'arcfour128': case 'arcfour256': if (!class_exists('Crypt_RC4')) { - require_once('Crypt/RC4.php'); + include_once 'Crypt/RC4.php'; } $this->encrypt = new Crypt_RC4(); break; @@ -1431,13 +1474,13 @@ class Net_SSH2 { switch ($decrypt) { case '3des-cbc': if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $this->decrypt = new Crypt_TripleDES(); break; case '3des-ctr': if (!class_exists('Crypt_TripleDES')) { - require_once('Crypt/TripleDES.php'); + include_once 'Crypt/TripleDES.php'; } $this->decrypt = new Crypt_TripleDES(CRYPT_DES_MODE_CTR); break; @@ -1445,7 +1488,7 @@ class Net_SSH2 { case 'aes192-cbc': case 'aes128-cbc': if (!class_exists('Crypt_Rijndael')) { - require_once('Crypt/Rijndael.php'); + include_once 'Crypt/Rijndael.php'; } $this->decrypt = new Crypt_Rijndael(); $this->decrypt_block_size = 16; @@ -1454,21 +1497,21 @@ class Net_SSH2 { case 'aes192-ctr': case 'aes128-ctr': if (!class_exists('Crypt_Rijndael')) { - require_once('Crypt/Rijndael.php'); + include_once 'Crypt/Rijndael.php'; } $this->decrypt = new Crypt_Rijndael(CRYPT_RIJNDAEL_MODE_CTR); $this->decrypt_block_size = 16; break; case 'blowfish-cbc': if (!class_exists('Crypt_Blowfish')) { - require_once('Crypt/Blowfish.php'); + include_once 'Crypt/Blowfish.php'; } $this->decrypt = new Crypt_Blowfish(); $this->decrypt_block_size = 8; break; case 'blowfish-ctr': if (!class_exists('Crypt_Blowfish')) { - require_once('Crypt/Blowfish.php'); + include_once 'Crypt/Blowfish.php'; } $this->decrypt = new Crypt_Blowfish(CRYPT_BLOWFISH_MODE_CTR); $this->decrypt_block_size = 8; @@ -1478,7 +1521,7 @@ class Net_SSH2 { case 'twofish256-cbc': case 'twofish-cbc': if (!class_exists('Crypt_Twofish')) { - require_once('Crypt/Twofish.php'); + include_once 'Crypt/Twofish.php'; } $this->decrypt = new Crypt_Twofish(); $this->decrypt_block_size = 16; @@ -1487,7 +1530,7 @@ class Net_SSH2 { case 'twofish192-ctr': case 'twofish256-ctr': if (!class_exists('Crypt_Twofish')) { - require_once('Crypt/Twofish.php'); + include_once 'Crypt/Twofish.php'; } $this->decrypt = new Crypt_Twofish(CRYPT_TWOFISH_MODE_CTR); $this->decrypt_block_size = 16; @@ -1496,7 +1539,7 @@ class Net_SSH2 { case 'arcfour128': case 'arcfour256': if (!class_exists('Crypt_RC4')) { - require_once('Crypt/RC4.php'); + include_once 'Crypt/RC4.php'; } $this->decrypt = new Crypt_RC4(); break; @@ -1647,10 +1690,26 @@ class Net_SSH2 { * @param Mixed $password * @param Mixed $... * @return Boolean - * @see _login_helper + * @see _login * @access public */ function login($username) + { + $args = func_get_args(); + return call_user_func_array(array(&$this, '_login'), $args); + } + + /** + * Login Helper + * + * @param String $username + * @param Mixed $password + * @param Mixed $... + * @return Boolean + * @see _login_helper + * @access private + */ + function _login($username) { $args = array_slice(func_get_args(), 1); if (empty($args)) { @@ -1710,8 +1769,13 @@ class Net_SSH2 { } // although PHP5's get_class() preserves the case, PHP4's does not - if (is_object($password) && strtolower(get_class($password)) == 'crypt_rsa') { - return $this->_privatekey_login($username, $password); + if (is_object($password)) { + switch (strtolower(get_class($password))) { + case 'crypt_rsa': + return $this->_privatekey_login($username, $password); + case 'system_ssh_agent': + return $this->_ssh_agent_login($username, $password); + } } if (is_array($password)) { @@ -1757,7 +1821,7 @@ class Net_SSH2 { // remove the username and password from the logged packet if (!defined('NET_SSH2_LOGGING')) { - $logged = NULL; + $logged = null; } else { $logged = pack('CNa*Na*Na*CNa*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection', @@ -1821,7 +1885,7 @@ class Net_SSH2 { */ function _keyboard_interactive_login($username, $password) { - $packet = pack('CNa*Na*Na*Na*Na*', + $packet = pack('CNa*Na*Na*Na*Na*', NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection', strlen('keyboard-interactive'), 'keyboard-interactive', 0, '', 0, '' ); @@ -1948,6 +2012,26 @@ class Net_SSH2 { return false; } + /** + * Login with an ssh-agent provided key + * + * @param String $username + * @param System_SSH_Agent $agent + * @return Boolean + * @access private + */ + function _ssh_agent_login($username, $agent) + { + $keys = $agent->requestIdentities(); + foreach ($keys as $key) { + if ($this->_privatekey_login($username, $key)) { + return true; + } + } + + return false; + } + /** * Login with an RSA private key * @@ -2056,7 +2140,7 @@ class Net_SSH2 { /** * Get the output from stdError - * + * * @access public */ function getStdError() @@ -2075,7 +2159,7 @@ class Net_SSH2 { * @return String * @access public */ - function exec($command, $callback = NULL) + function exec($command, $callback = null) { $this->curTimeout = $this->timeout; $this->is_timeout = false; @@ -2086,7 +2170,7 @@ class Net_SSH2 { } // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to - // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but, + // be adjusted". 0x7FFFFFFF is, at 2GB, the max size. technically, it should probably be decremented, but, // honestly, if you're transfering more than 2GB, you probably shouldn't be using phpseclib, anyway. // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info $this->window_size_server_to_client[NET_SSH2_CHANNEL_EXEC] = 0x7FFFFFFF; @@ -2143,7 +2227,7 @@ class Net_SSH2 { // neither will your script. // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by - // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the + // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA. RFC4254#section-5.2 corroborates. $packet = pack('CNNa*CNa*', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('exec'), 'exec', 1, strlen($command), $command); @@ -2349,7 +2433,6 @@ class Net_SSH2 { return false; } - $channel = $this->in_request_pty_exec ? NET_SSH2_CHANNEL_EXEC : NET_SSH2_CHANNEL_SHELL; return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd); } @@ -2430,8 +2513,7 @@ class Net_SSH2 { */ function reset() { - $channel = $this->in_request_pty_exec ? NET_SSH2_CHANNEL_EXEC : NET_SSH2_CHANNEL_SHELL; - $this->_close_channel($channel); + $this->_close_channel($this->_get_interactive_channel()); } /** @@ -2724,7 +2806,7 @@ class Net_SSH2 { } $read = array($this->fsock); - $write = $except = NULL; + $write = $except = null; $start = strtok(microtime(), ' ') + strtok(''); // http://php.net/microtime#61838 $sec = floor($this->curTimeout); @@ -2801,7 +2883,7 @@ class Net_SSH2 { /* if ($channel == NET_SSH2_CHANNEL_EXEC) { // SCP requires null packets, such as this, be sent. further, in the case of the ssh.com SSH server - // this actually seems to make things twice as fast. more to the point, the message right after + // this actually seems to make things twice as fast. more to the point, the message right after // SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise. // in OpenSSH it slows things down but only by a couple thousandths of a second. $this->_send_channel_packet($channel, chr(0)); @@ -2861,12 +2943,9 @@ class Net_SSH2 { case 'exit-status': extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5))); $this->exit_status = $exit_status; - // "The channel needs to be closed with SSH_MSG_CHANNEL_CLOSE after this message." - // -- http://tools.ietf.org/html/rfc4254#section-6.10 - $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel])); - $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF; + // "The client MAY ignore these messages." + // -- http://tools.ietf.org/html/rfc4254#section-6.10 break; default: @@ -2907,7 +2986,7 @@ class Net_SSH2 { * @return Boolean * @access private */ - function _send_binary_packet($data, $logged = NULL) + function _send_binary_packet($data, $logged = null) { if (!is_resource($this->fsock) || feof($this->fsock)) { user_error('Connection closed prematurely'); @@ -2967,70 +3046,70 @@ class Net_SSH2 { */ function _append_log($message_number, $message) { - // remove the byte identifying the message type from all but the first two messages (ie. the identification strings) - if (strlen($message_number) > 2) { - $this->_string_shift($message); - } + // remove the byte identifying the message type from all but the first two messages (ie. the identification strings) + if (strlen($message_number) > 2) { + $this->_string_shift($message); + } - switch (NET_SSH2_LOGGING) { - // useful for benchmarks - case NET_SSH2_LOG_SIMPLE: - $this->message_number_log[] = $message_number; - break; - // the most useful log for SSH2 - case NET_SSH2_LOG_COMPLEX: - $this->message_number_log[] = $message_number; - $this->log_size+= strlen($message); - $this->message_log[] = $message; - while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) { - $this->log_size-= strlen(array_shift($this->message_log)); - array_shift($this->message_number_log); - } - break; - // dump the output out realtime; packets may be interspersed with non packets, - // passwords won't be filtered out and select other packets may not be correctly - // identified - case NET_SSH2_LOG_REALTIME: - switch (PHP_SAPI) { - case 'cli': - $start = $stop = "\r\n"; - break; - default: - $start = '
';
-                            $stop = '
'; - } - echo $start . $this->_format_log(array($message), array($message_number)) . $stop; - @flush(); - @ob_flush(); - break; - // basically the same thing as NET_SSH2_LOG_REALTIME with the caveat that NET_SSH2_LOG_REALTIME_FILE - // needs to be defined and that the resultant log file will be capped out at NET_SSH2_LOG_MAX_SIZE. - // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily - // at the beginning of the file - case NET_SSH2_LOG_REALTIME_FILE: - if (!isset($this->realtime_log_file)) { - // PHP doesn't seem to like using constants in fopen() - $filename = NET_SSH2_LOG_REALTIME_FILENAME; - $fp = fopen($filename, 'w'); - $this->realtime_log_file = $fp; - } - if (!is_resource($this->realtime_log_file)) { + switch (NET_SSH2_LOGGING) { + // useful for benchmarks + case NET_SSH2_LOG_SIMPLE: + $this->message_number_log[] = $message_number; + break; + // the most useful log for SSH2 + case NET_SSH2_LOG_COMPLEX: + $this->message_number_log[] = $message_number; + $this->log_size+= strlen($message); + $this->message_log[] = $message; + while ($this->log_size > NET_SSH2_LOG_MAX_SIZE) { + $this->log_size-= strlen(array_shift($this->message_log)); + array_shift($this->message_number_log); + } + break; + // dump the output out realtime; packets may be interspersed with non packets, + // passwords won't be filtered out and select other packets may not be correctly + // identified + case NET_SSH2_LOG_REALTIME: + switch (PHP_SAPI) { + case 'cli': + $start = $stop = "\r\n"; break; - } - $entry = $this->_format_log(array($message), array($message_number)); - if ($this->realtime_log_wrap) { - $temp = "<<< START >>>\r\n"; - $entry.= $temp; - fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); - } - $this->realtime_log_size+= strlen($entry); - if ($this->realtime_log_size > NET_SSH2_LOG_MAX_SIZE) { - fseek($this->realtime_log_file, 0); - $this->realtime_log_size = strlen($entry); - $this->realtime_log_wrap = true; - } - fputs($this->realtime_log_file, $entry); - } + default: + $start = '
';
+                        $stop = '
'; + } + echo $start . $this->_format_log(array($message), array($message_number)) . $stop; + @flush(); + @ob_flush(); + break; + // basically the same thing as NET_SSH2_LOG_REALTIME with the caveat that NET_SSH2_LOG_REALTIME_FILE + // needs to be defined and that the resultant log file will be capped out at NET_SSH2_LOG_MAX_SIZE. + // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily + // at the beginning of the file + case NET_SSH2_LOG_REALTIME_FILE: + if (!isset($this->realtime_log_file)) { + // PHP doesn't seem to like using constants in fopen() + $filename = NET_SSH2_LOG_REALTIME_FILENAME; + $fp = fopen($filename, 'w'); + $this->realtime_log_file = $fp; + } + if (!is_resource($this->realtime_log_file)) { + break; + } + $entry = $this->_format_log(array($message), array($message_number)); + if ($this->realtime_log_wrap) { + $temp = "<<< START >>>\r\n"; + $entry.= $temp; + fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); + } + $this->realtime_log_size+= strlen($entry); + if ($this->realtime_log_size > NET_SSH2_LOG_MAX_SIZE) { + fseek($this->realtime_log_file, 0); + $this->realtime_log_size = strlen($entry); + $this->realtime_log_wrap = true; + } + fputs($this->realtime_log_file, $entry); + } } /** @@ -3103,16 +3182,19 @@ class Net_SSH2 { * for SCP more than anything. * * @param Integer $client_channel + * @param Boolean $want_reply * @return Boolean * @access private */ - function _close_channel($client_channel) + function _close_channel($client_channel, $want_reply = false) { // see http://tools.ietf.org/html/rfc4254#section-5.3 $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel])); - $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); + if (!$want_reply) { + $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); + } $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE; @@ -3120,6 +3202,10 @@ class Net_SSH2 { while (!is_bool($this->_get_channel_packet($client_channel))); + if ($want_reply) { + $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel])); + } + if ($this->bitmap & NET_SSH2_MASK_SHELL) { $this->bitmap&= ~NET_SSH2_MASK_SHELL; } @@ -3220,8 +3306,6 @@ class Net_SSH2 { */ function _format_log($message_log, $message_number_log) { - static $boundary = ':', $long_width = 65, $short_width = 16; - $output = ''; for ($i = 0; $i < count($message_log); $i++) { $output.= $message_number_log[$i] . "\r\n"; @@ -3231,19 +3315,13 @@ class Net_SSH2 { if (strlen($current_log)) { $output.= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0 '; } - $fragment = $this->_string_shift($current_log, $short_width); - $hex = substr( - preg_replace( - '#(.)#es', - '"' . $boundary . '" . str_pad(dechex(ord(substr("\\1", -1))), 2, "0", STR_PAD_LEFT)', - $fragment), - strlen($boundary) - ); + $fragment = $this->_string_shift($current_log, $this->log_short_width); + $hex = substr(preg_replace_callback('#.#s', array($this, '_format_log_helper'), $fragment), strlen($this->log_boundary)); // replace non ASCII printable characters with dots // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters // also replace < with a . since < messes up the output on web browsers $raw = preg_replace('#[^\x20-\x7E]|<#', '.', $fragment); - $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n"; + $output.= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n"; $j++; } while (strlen($current_log)); $output.= "\r\n"; @@ -3252,6 +3330,20 @@ class Net_SSH2 { return $output; } + /** + * Helper function for _format_log + * + * For use with preg_replace_callback() + * + * @param Array $matches + * @access private + * @return String + */ + function _format_log_helper($matches) + { + return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT); + } + /** * Returns all errors * @@ -3505,7 +3597,7 @@ class Net_SSH2 { $signature = $this->_string_shift($signature, $temp['length']); if (!class_exists('Crypt_RSA')) { - require_once('Crypt/RSA.php'); + include_once 'Crypt/RSA.php'; } $rsa = new Crypt_RSA(); @@ -3572,7 +3664,15 @@ class Net_SSH2 { */ function _is_includable($suffix) { - foreach (explode(PATH_SEPARATOR, get_include_path()) as $prefix) { + // stream_resolve_include_path was introduced in PHP 5.3.2 + if (function_exists('stream_resolve_include_path')) { + return stream_resolve_include_path($suffix) !== false; + } + + $paths = PATH_SEPARATOR == ':' ? + preg_split('#(? + * login('username', $agent)) { + * exit('Login Failed'); + * } + * + * echo $ssh->exec('pwd'); + * echo $ssh->exec('ls -la'); + * ?> + * + * + * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @category System + * @package System_SSH_Agent + * @author Jim Wigginton + * @copyright MMXIV Jim Wigginton + * @license http://www.opensource.org/licenses/mit-license.html MIT License + * @link http://phpseclib.sourceforge.net + * @internal See http://api.libssh.org/rfc/PROTOCOL.agent + */ + +/**#@+ + * Message numbers + * + * @access private + */ +// to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1) +define('SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES', 11); +// this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2). +define('SYSTEM_SSH_AGENT_IDENTITIES_ANSWER', 12); +define('SYSTEM_SSH_AGENT_FAILURE', 5); +// the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3) +define('SYSTEM_SSH_AGENTC_SIGN_REQUEST', 13); +// the SSH1 response is SSH_AGENT_RSA_RESPONSE (4) +define('SYSTEM_SSH_AGENT_SIGN_RESPONSE', 14); +/**#@-*/ + +/** + * Pure-PHP ssh-agent client identity object + * + * Instantiation should only be performed by System_SSH_Agent class. + * This could be thought of as implementing an interface that Crypt_RSA + * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something. + * The methods in this interface would be getPublicKey, setSignatureMode + * and sign since those are the methods phpseclib looks for to perform + * public key authentication. + * + * @package System_SSH_Agent + * @author Jim Wigginton + * @version 0.1.0 + * @access internal + */ +class System_SSH_Agent_Identity +{ + /** + * Key Object + * + * @var Crypt_RSA + * @access private + * @see System_SSH_Agent_Identity::getPublicKey() + */ + var $key; + + /** + * Key Blob + * + * @var String + * @access private + * @see System_SSH_Agent_Identity::sign() + */ + var $key_blob; + + /** + * Socket Resource + * + * @var Resource + * @access private + * @see System_SSH_Agent_Identity::sign() + */ + var $fsock; + + /** + * Default Constructor. + * + * @param Resource $fsock + * @return System_SSH_Agent_Identity + * @access private + */ + function System_SSH_Agent_Identity($fsock) + { + $this->fsock = $fsock; + } + + /** + * Set Public Key + * + * Called by System_SSH_Agent::requestIdentities() + * + * @param Crypt_RSA $key + * @access private + */ + function setPublicKey($key) + { + $this->key = $key; + $this->key->setPublicKey(); + } + + /** + * Set Public Key + * + * Called by System_SSH_Agent::requestIdentities(). The key blob could be extracted from $this->key + * but this saves a small amount of computation. + * + * @param String $key_blob + * @access private + */ + function setPublicKeyBlob($key_blob) + { + $this->key_blob = $key_blob; + } + + /** + * Get Public Key + * + * Wrapper for $this->key->getPublicKey() + * + * @param Integer $format optional + * @return Mixed + * @access public + */ + function getPublicKey($format = null) + { + return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format); + } + + /** + * Set Signature Mode + * + * Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie. + * ssh-agent's only supported mode is CRYPT_RSA_SIGNATURE_PKCS1 + * + * @param Integer $mode + * @access public + */ + function setSignatureMode($mode) + { + } + + /** + * Create a signature + * + * See "2.6.2 Protocol 2 private key signature request" + * + * @param String $message + * @return String + * @access public + */ + function sign($message) + { + // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE + $packet = pack('CNa*Na*N', SYSTEM_SSH_AGENTC_SIGN_REQUEST, strlen($this->key_blob), $this->key_blob, strlen($message), $message, 0); + $packet = pack('Na*', strlen($packet), $packet); + if (strlen($packet) != fputs($this->fsock, $packet)) { + user_error('Connection closed during signing'); + } + + $length = current(unpack('N', fread($this->fsock, 4))); + $type = ord(fread($this->fsock, 1)); + if ($type != SYSTEM_SSH_AGENT_SIGN_RESPONSE) { + user_error('Unable to retreive signature'); + } + + $signature_blob = fread($this->fsock, $length - 1); + // the only other signature format defined - ssh-dss - is the same length as ssh-rsa + // the + 12 is for the other various SSH added length fields + return substr($signature_blob, strlen('ssh-rsa') + 12); + } +} + +/** + * Pure-PHP ssh-agent client identity factory + * + * requestIdentities() method pumps out System_SSH_Agent_Identity objects + * + * @package System_SSH_Agent + * @author Jim Wigginton + * @version 0.1.0 + * @access internal + */ +class System_SSH_Agent +{ + /** + * Socket Resource + * + * @var Resource + * @access private + */ + var $fsock; + + /** + * Default Constructor + * + * @return System_SSH_Agent + * @access public + */ + function System_SSH_Agent() + { + switch (true) { + case isset($_SERVER['SSH_AUTH_SOCK']): + $address = $_SERVER['SSH_AUTH_SOCK']; + break; + case isset($_ENV['SSH_AUTH_SOCK']): + $address = $_ENV['SSH_AUTH_SOCK']; + break; + default: + user_error('SSH_AUTH_SOCK not found'); + return false; + } + + $this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr); + if (!$this->fsock) { + user_error("Unable to connect to ssh-agent (Error $errno: $errstr)"); + } + } + + /** + * Request Identities + * + * See "2.5.2 Requesting a list of protocol 2 keys" + * Returns an array containing zero or more System_SSH_Agent_Identity objects + * + * @return Array + * @access public + */ + function requestIdentities() + { + if (!$this->fsock) { + return array(); + } + + $packet = pack('NC', 1, SYSTEM_SSH_AGENTC_REQUEST_IDENTITIES); + if (strlen($packet) != fputs($this->fsock, $packet)) { + user_error('Connection closed while requesting identities'); + } + + $length = current(unpack('N', fread($this->fsock, 4))); + $type = ord(fread($this->fsock, 1)); + if ($type != SYSTEM_SSH_AGENT_IDENTITIES_ANSWER) { + user_error('Unable to request identities'); + } + + $identities = array(); + $keyCount = current(unpack('N', fread($this->fsock, 4))); + for ($i = 0; $i < $keyCount; $i++) { + $length = current(unpack('N', fread($this->fsock, 4))); + $key_blob = fread($this->fsock, $length); + $length = current(unpack('N', fread($this->fsock, 4))); + $key_comment = fread($this->fsock, $length); + $length = current(unpack('N', substr($key_blob, 0, 4))); + $key_type = substr($key_blob, 4, $length); + switch ($key_type) { + case 'ssh-rsa': + if (!class_exists('Crypt_RSA')) { + include_once 'Crypt/RSA.php'; + } + $key = new Crypt_RSA(); + $key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment); + break; + case 'ssh-dss': + // not currently supported + break; + } + // resources are passed by reference by default + if (isset($key)) { + $identity = new System_SSH_Agent_Identity($this->fsock); + $identity->setPublicKey($key); + $identity->setPublicKeyBlob($key_blob); + $identities[] = $identity; + unset($key); + } + } + + return $identities; + } +} diff --git a/apps/files_external/3rdparty/phpseclib/phpseclib/openssl.cnf b/apps/files_external/3rdparty/phpseclib/phpseclib/openssl.cnf index 6baa566102c71629a2cb669f6d96d414e6f0e37d..2b8b52f9f7fc75fa8a7e0f6244712fb523adedc1 100644 --- a/apps/files_external/3rdparty/phpseclib/phpseclib/openssl.cnf +++ b/apps/files_external/3rdparty/phpseclib/phpseclib/openssl.cnf @@ -3,4 +3,4 @@ HOME = . RANDFILE = $ENV::HOME/.rnd -[ v3_ca ] \ No newline at end of file +[ v3_ca ] diff --git a/apps/files_external/3rdparty/smb4php/smb.php b/apps/files_external/3rdparty/smb4php/smb.php index 656930514f0d689a16ed3c088afe266fbea114bd..e325506fa147eeac74018de5875346ee1f69a46c 100644 --- a/apps/files_external/3rdparty/smb4php/smb.php +++ b/apps/files_external/3rdparty/smb4php/smb.php @@ -8,6 +8,8 @@ # Homepage: http://www.phpclasses.org/smb4php # # Copyright (c) 2007 Victor M. Varela +# Copyright (c) 2012 Frank Karlitschek +# Copyright (c) 2014 Robin McCorkell # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -19,8 +21,6 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # -# Addition 17/12/2012 Frank Karlitschek (frank@owncloud.org) -# Addition 17/03/2014 Robin McCorkell (rmccorkell@karoshi.org.uk) # On the official website http://www.phpclasses.org/smb4php the # license is listed as LGPL so we assume that this is # dual-licensed GPL/LGPL @@ -44,6 +44,42 @@ $GLOBALS['__smb_cache'] = array ('stat' => array (), 'dir' => array ()); class smb { + private static $regexp = array ( + '^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip', + 'Anonymous login successful' => 'skip', + '^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip', + '^\tSharename[ ]+Type[ ]+Comment$' => 'shares', + '^\t---------[ ]+----[ ]+-------$' => 'skip', + '^\tServer [ ]+Comment$' => 'servers', + '^\t---------[ ]+-------$' => 'skip', + '^\tWorkgroup[ ]+Master$' => 'workg', + '^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip', + '^\tIPC\\\$(.*)[ ]+IPC' => 'skip', + '^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share', + '^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip', + '([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip', + 'Got a positive name query response from ' => 'skip', + '^(session setup failed): (.*)$' => 'error', + '^(.*): ERRSRV - ERRbadpw' => 'error', + '^Error returning browse list: (.*)$' => 'error', + '^tree connect failed: (.*)$' => 'error', + '^(Connection to .* failed)(.*)$' => 'error-connect', + '^NT_STATUS_(.*) ' => 'error', + '^NT_STATUS_(.*)\$' => 'error', + 'ERRDOS - ERRbadpath \((.*).\)' => 'error', + 'cd (.*): (.*)$' => 'error', + '^cd (.*): NT_STATUS_(.*)' => 'error', + '^\t(.*)$' => 'srvorwg', + '^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip', + '^Job ([0-9]+) cancelled' => 'skip', + '^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files', + '^message start: ERRSRV - (ERRmsgoff)' => 'error' + ); + + function getRegexp() { + return self::$regexp; + } + function parse_url ($url) { $pu = parse_url (trim($url)); foreach (array ('domain', 'user', 'pass', 'host', 'port', 'path') as $i) { @@ -75,46 +111,16 @@ class smb { } - function execute ($command, $purl) { + function execute ($command, $purl, $regexp = NULL) { return smb::client ('-d 0 ' . escapeshellarg ('//' . $purl['host'] . '/' . $purl['share']) - . ' -c ' . escapeshellarg ($command), $purl + . ' -c ' . escapeshellarg ($command), $purl, $regexp ); } - function client ($params, $purl) { - - static $regexp = array ( - '^added interface ip=(.*) bcast=(.*) nmask=(.*)$' => 'skip', - 'Anonymous login successful' => 'skip', - '^Domain=\[(.*)\] OS=\[(.*)\] Server=\[(.*)\]$' => 'skip', - '^\tSharename[ ]+Type[ ]+Comment$' => 'shares', - '^\t---------[ ]+----[ ]+-------$' => 'skip', - '^\tServer [ ]+Comment$' => 'servers', - '^\t---------[ ]+-------$' => 'skip', - '^\tWorkgroup[ ]+Master$' => 'workg', - '^\t(.*)[ ]+(Disk|IPC)[ ]+IPC.*$' => 'skip', - '^\tIPC\\\$(.*)[ ]+IPC' => 'skip', - '^\t(.*)[ ]+(Disk)[ ]+(.*)$' => 'share', - '^\t(.*)[ ]+(Printer)[ ]+(.*)$' => 'skip', - '([0-9]+) blocks of size ([0-9]+)\. ([0-9]+) blocks available' => 'skip', - 'Got a positive name query response from ' => 'skip', - '^(session setup failed): (.*)$' => 'error', - '^(.*): ERRSRV - ERRbadpw' => 'error', - '^Error returning browse list: (.*)$' => 'error', - '^tree connect failed: (.*)$' => 'error', - '^(Connection to .* failed)(.*)$' => 'error-connect', - '^NT_STATUS_(.*) ' => 'error', - '^NT_STATUS_(.*)\$' => 'error', - 'ERRDOS - ERRbadpath \((.*).\)' => 'error', - 'cd (.*): (.*)$' => 'error', - '^cd (.*): NT_STATUS_(.*)' => 'error', - '^\t(.*)$' => 'srvorwg', - '^([0-9]+)[ ]+([0-9]+)[ ]+(.*)$' => 'skip', - '^Job ([0-9]+) cancelled' => 'skip', - '^[ ]+(.*)[ ]+([0-9]+)[ ]+(Mon|Tue|Wed|Thu|Fri|Sat|Sun)[ ](Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]+([0-9]+)[ ]+([0-9]{2}:[0-9]{2}:[0-9]{2})[ ]([0-9]{4})$' => 'files', - '^message start: ERRSRV - (ERRmsgoff)' => 'error' - ); + function client ($params, $purl, $regexp = NULL) { + + if ($regexp === NULL) $regexp = smb::$regexp; if (SMB4PHP_AUTHMODE == 'env') { putenv("USER={$purl['user']}%{$purl['pass']}"); diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php index 0e83660f845e6401dd966c60c35d1a88f2f29424..0017b22caaddfe55e4830c2e7d0670f370004d37 100644 --- a/apps/files_external/appinfo/app.php +++ b/apps/files_external/appinfo/app.php @@ -1,6 +1,7 @@ + * Copyright (c) 2014 Robin McCorkell * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -13,6 +14,7 @@ OC::$CLASSPATH['OC\Files\Storage\OwnCloud'] = 'files_external/lib/owncloud.php'; OC::$CLASSPATH['OC\Files\Storage\Google'] = 'files_external/lib/google.php'; OC::$CLASSPATH['OC\Files\Storage\Swift'] = 'files_external/lib/swift.php'; OC::$CLASSPATH['OC\Files\Storage\SMB'] = 'files_external/lib/smb.php'; +OC::$CLASSPATH['OC\Files\Storage\SMB_OC'] = 'files_external/lib/smb_oc.php'; OC::$CLASSPATH['OC\Files\Storage\AmazonS3'] = 'files_external/lib/amazons3.php'; OC::$CLASSPATH['OC\Files\Storage\Dropbox'] = 'files_external/lib/dropbox.php'; OC::$CLASSPATH['OC\Files\Storage\SFTP'] = 'files_external/lib/sftp.php'; @@ -27,4 +29,138 @@ if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == ' // connecting hooks OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OC_Mount_Config', 'initMountPointsHook'); OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\iRODS', 'login'); +OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\SMB_OC', 'login'); +OC_Mount_Config::registerBackend('\OC\Files\Storage\Local', array( + 'backend' => 'Local', + 'configuration' => array( + 'datadir' => 'Location'))); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\AmazonS3', array( + 'backend' => 'Amazon S3', + 'configuration' => array( + 'key' => 'Key', + 'secret' => '*Secret', + 'bucket' => 'Bucket'), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\AmazonS3', array( + 'backend' => 'Amazon S3 and compliant', + 'configuration' => array( + 'key' => 'Access Key', + 'secret' => '*Secret Key', + 'bucket' => 'Bucket', + 'hostname' => '&Hostname (optional)', + 'port' => '&Port (optional)', + 'region' => '&Region (optional)', + 'use_ssl' => '!Enable SSL', + 'use_path_style' => '!Enable Path Style'), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\Dropbox', array( + 'backend' => 'Dropbox', + 'configuration' => array( + 'configured' => '#configured', + 'app_key' => 'App key', + 'app_secret' => '*App secret', + 'token' => '#token', + 'token_secret' => '#token_secret'), + 'custom' => 'dropbox', + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\FTP', array( + 'backend' => 'FTP', + 'configuration' => array( + 'host' => 'URL', + 'user' => 'Username', + 'password' => '*Password', + 'root' => '&Root', + 'secure' => '!Secure ftps://'), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\Google', array( + 'backend' => 'Google Drive', + 'configuration' => array( + 'configured' => '#configured', + 'client_id' => 'Client ID', + 'client_secret' => '*Client secret', + 'token' => '#token'), + 'custom' => 'google', + 'has_dependencies' => true)); + + +OC_Mount_Config::registerBackend('\OC\Files\Storage\Swift', array( + 'backend' => 'OpenStack Object Storage', + 'configuration' => array( + 'user' => 'Username (required)', + 'bucket' => 'Bucket (required)', + 'region' => '&Region (optional for OpenStack Object Storage)', + 'key' => '*API Key (required for Rackspace Cloud Files)', + 'tenant' => '&Tenantname (required for OpenStack Object Storage)', + 'password' => '*Password (required for OpenStack Object Storage)', + 'service_name' => '&Service Name (required for OpenStack Object Storage)', + 'url' => '&URL of identity endpoint (required for OpenStack Object Storage)', + 'timeout' => '&Timeout of HTTP requests in seconds (optional)', + ), + 'has_dependencies' => true)); + + +if (!OC_Util::runningOnWindows()) { + OC_Mount_Config::registerBackend('\OC\Files\Storage\SMB', array( + 'backend' => 'SMB / CIFS', + 'configuration' => array( + 'host' => 'URL', + 'user' => 'Username', + 'password' => '*Password', + 'share' => 'Share', + 'root' => '&Root'), + 'has_dependencies' => true)); + + OC_Mount_Config::registerBackend('\OC\Files\Storage\SMB_OC', array( + 'backend' => 'SMB / CIFS using OC login', + 'configuration' => array( + 'host' => 'URL', + 'username_as_share' => '!Username as share', + 'share' => '&Share', + 'root' => '&Root'), + 'has_dependencies' => true)); +} + +OC_Mount_Config::registerBackend('\OC\Files\Storage\DAV', array( + 'backend' => 'WebDAV', + 'configuration' => array( + 'host' => 'URL', + 'user' => 'Username', + 'password' => '*Password', + 'root' => '&Root', + 'secure' => '!Secure https://'), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\OwnCloud', array( + 'backend' => 'ownCloud', + 'configuration' => array( + 'host' => 'URL', + 'user' => 'Username', + 'password' => '*Password', + 'root' => '&Remote subfolder', + 'secure' => '!Secure https://'))); + + +OC_Mount_Config::registerBackend('\OC\Files\Storage\SFTP', array( + 'backend' => 'SFTP', + 'configuration' => array( + 'host' => 'URL', + 'user' => 'Username', + 'password' => '*Password', + 'root' => '&Root'))); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\iRODS', array( + 'backend' => 'iRODS', + 'configuration' => array( + 'host' => 'Host', + 'port' => 'Port', + 'use_logon_credentials' => '!Use ownCloud login', + 'user' => 'Username', + 'password' => '*Password', + 'auth_mode' => 'Authentication Mode', + 'zone' => 'Zone'))); diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index cd2a3103eb72365656fddc715ecf7edc2883e73f..00793a614c20f5e3be668404cb84b003350e9ebe 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -181,16 +181,21 @@ $(document).ready(function() { $.each(configurations, function(backend, parameters) { if (backend == backendClass) { $.each(parameters['configuration'], function(parameter, placeholder) { - if (placeholder.indexOf('*') != -1) { - td.append(''); - } else if (placeholder.indexOf('!') != -1) { + var is_optional = false; + if (placeholder.indexOf('&') === 0) { + is_optional = true; + placeholder = placeholder.substring(1); + } + if (placeholder.indexOf('*') === 0) { + var class_string = is_optional ? ' class="optional"' : ''; + td.append(''); + } else if (placeholder.indexOf('!') === 0) { td.append(''); - } else if (placeholder.indexOf('&') != -1) { - td.append(''); - } else if (placeholder.indexOf('#') != -1) { + } else if (placeholder.indexOf('#') === 0) { td.append(''); } else { - td.append(''); + var class_string = is_optional ? ' class="optional"' : ''; + td.append(''); } }); if (parameters['custom'] && $('#externalStorage tbody tr.'+backendClass.replace(/\\/g, '\\\\')).length == 1) { diff --git a/apps/files_external/l10n/ast.php b/apps/files_external/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..7061cffaa8e78f3e02cfd1e788b41ffc909e4bb2 --- /dev/null +++ b/apps/files_external/l10n/ast.php @@ -0,0 +1,9 @@ + "Nome de la carpeta", +"Options" => "Opciones", +"Groups" => "Grupos", +"Users" => "Usuarios", +"Delete" => "Desaniciar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/bg_BG.php b/apps/files_external/l10n/bg_BG.php index d59a4b8c80bc64184dafd189a8839f5a6165ff48..118da27f74a4cf4772cc86d45a71e56fdce178cd 100644 --- a/apps/files_external/l10n/bg_BG.php +++ b/apps/files_external/l10n/bg_BG.php @@ -6,8 +6,6 @@ $TRANSLATIONS = array( "Folder name" => "Име на папката", "Configuration" => "Конфигурация", "Options" => "Опции", -"Applicable" => "Приложимо", -"None set" => "Няма избрано", "All Users" => "Всички потребители", "Groups" => "Групи", "Users" => "Потребители", diff --git a/apps/files_external/l10n/bn_BD.php b/apps/files_external/l10n/bn_BD.php index 065d61acfca5633fdb08650cc3a0b69ec3d29f1d..6c8f57779583d2898305f95cdf2ed45452ae34ea 100644 --- a/apps/files_external/l10n/bn_BD.php +++ b/apps/files_external/l10n/bn_BD.php @@ -8,8 +8,6 @@ $TRANSLATIONS = array( "External Storage" => "বাহ্যিক সংরক্ষণাগার", "Configuration" => "কনফিগারেসন", "Options" => "বিকল্পসমূহ", -"Applicable" => "প্রযোজ্য", -"None set" => "কোনটিই নির্ধারণ করা হয় নি", "All Users" => "সমস্ত ব্যবহারকারী", "Groups" => "গোষ্ঠীসমূহ", "Users" => "ব্যবহারকারী", diff --git a/apps/files_external/l10n/ca.php b/apps/files_external/l10n/ca.php index 3e72204629685bcdf8aebff503abbafc398a018f..50b6f55231bd6db97e51ee54fe047e4ceb3550c6 100644 --- a/apps/files_external/l10n/ca.php +++ b/apps/files_external/l10n/ca.php @@ -6,17 +6,12 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Proporcioneu una clau d'aplicació i secret vàlids per a Dropbox", "Error configuring Google Drive storage" => "Error en configurar l'emmagatzemament Google Drive", "Saved" => "Desat", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Avís: \"smbclient\" no està instal·lat. No es pot muntar la compartició CIFS/SMB. Demaneu a l'administrador del sistema que l'instal·li.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Avís: El suport FTP per PHP no està activat o no està instal·lat. No es pot muntar la compartició FTP. Demaneu a l'administrador del sistema que l'instal·li.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Avís:El suport Curl de PHP no està activat o instal·lat. No es pot muntar ownCloud / WebDAV o GoogleDrive. Demaneu a l'administrador que l'instal·li.", "External Storage" => "Emmagatzemament extern", "Folder name" => "Nom de la carpeta", "External storage" => "Emmagatzemament extern", "Configuration" => "Configuració", "Options" => "Options", -"Applicable" => "Aplicable", "Add storage" => "Afegeix emmagatzemament", -"None set" => "Cap d'establert", "All Users" => "Tots els usuaris", "Groups" => "Grups", "Users" => "Usuaris", diff --git a/apps/files_external/l10n/cs_CZ.php b/apps/files_external/l10n/cs_CZ.php index 1b92e35c45607551a86df634666b773aaba0f027..6a4e09aa3ab4bf668cd997a4840966e5b607cd41 100644 --- a/apps/files_external/l10n/cs_CZ.php +++ b/apps/files_external/l10n/cs_CZ.php @@ -6,17 +6,12 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Zadejte, prosím, platný klíč a bezpečnostní frázi aplikace Dropbox.", "Error configuring Google Drive storage" => "Chyba při nastavení úložiště Google Drive", "Saved" => "Uloženo", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Varování: není nainstalován program \"smbclient\". Není možné připojení oddílů CIFS/SMB. Prosím požádejte svého správce systému ať jej nainstaluje.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Varování: podpora FTP v PHP není povolena nebo není nainstalována. Není možné připojení oddílů FTP. Prosím požádejte svého správce systému ať ji nainstaluje.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Varování: podpora CURL v PHP není povolena nebo není nainstalována. Není možné připojení oddílů ownCloud, WebDAV, či GoogleDrive. Prosím požádejte svého správce systému ať ji nainstaluje.", "External Storage" => "Externí úložiště", "Folder name" => "Název složky", "External storage" => "Externí úložiště", "Configuration" => "Nastavení", "Options" => "Možnosti", -"Applicable" => "Přístupný pro", "Add storage" => "Přidat úložiště", -"None set" => "Nenastaveno", "All Users" => "Všichni uživatelé", "Groups" => "Skupiny", "Users" => "Uživatelé", diff --git a/apps/files_external/l10n/da.php b/apps/files_external/l10n/da.php index f3ac35e42e03ca4a5481c005ae9b7abfda5f282a..e0dea75303e0780a771e9fb812de7a647f3ca8b1 100644 --- a/apps/files_external/l10n/da.php +++ b/apps/files_external/l10n/da.php @@ -6,17 +6,12 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Angiv venligst en valid Dropbox app nøgle og hemmelighed", "Error configuring Google Drive storage" => "Fejl ved konfiguration af Google Drive plads", "Saved" => "Gemt", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => " Advarsel: \"smbclient\" ikke er installeret. Montering af CIFS / SMB delinger er ikke muligt. Spørg din systemadministrator om at installere det.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => " Advarsel: FTP-understøttelse i PHP ikke er aktiveret eller installeret. Montering af FTP delinger er ikke muligt. Spørg din systemadministrator om at installere det.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Advarsel: Understøttelsen for Curl i PHP er enten ikke aktiveret eller ikke installeret. Det er ikke muligt, at montere ownCloud / WebDAV eller GoogleDrive. Spørg din system administrator om at installere det. ", "External Storage" => "Ekstern opbevaring", "Folder name" => "Mappenavn", "External storage" => "Eksternt lager", "Configuration" => "Opsætning", "Options" => "Valgmuligheder", -"Applicable" => "Kan anvendes", "Add storage" => "Tilføj lager", -"None set" => "Ingen sat", "All Users" => "Alle brugere", "Groups" => "Grupper", "Users" => "Brugere", diff --git a/apps/files_external/l10n/de.php b/apps/files_external/l10n/de.php index a78728b4c20173745c2d25ba693716edff9df60a..25c7ffb3af185b5b2529ddf4c94837248b6c7bac 100644 --- a/apps/files_external/l10n/de.php +++ b/apps/files_external/l10n/de.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Bitte trage einen gültigen Dropbox-App-Key mit Secret ein.", "Error configuring Google Drive storage" => "Fehler beim Einrichten von Google Drive", "Saved" => "Gespeichert", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Warnung: \"smbclient\" ist nicht installiert. Das Einhängen von CIFS/SMB-Freigaben ist nicht möglich. Bitte Deinen System-Administrator, dies zu installieren.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Warnung:: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Bitte wende Dich an Deinen Systemadministrator.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Warnung: Die Curl-Unterstützung in PHP ist nicht aktiviert oder installiert. Das Einbinden von ownCloud / WebDav der GoogleDrive-Freigaben ist nicht möglich. Bitte Deinen Systemadminstrator um die Installation. ", +"Note: " => "Hinweis: ", +" and " => "und", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Hinweis: Die cURL-Unterstützung von PHP ist nicht aktiviert oder installiert. Das Hinzufügen von %s ist nicht möglich. Bitte wende Dich zur Installation an Deinen Systemadministrator.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Hinweis: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Das Hinzufügen von %s ist nicht möglich. Bitte wende Dich sich zur Installation an Deinen Systemadministrator.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Hinweis: \"%s\" ist nicht installiert. Das Hinzufügen von %s ist nicht möglich. Bitte wende Dich sich zur Installation an Deinen Systemadministrator.", "External Storage" => "Externer Speicher", "Folder name" => "Ordnername", "External storage" => "Externer Speicher", "Configuration" => "Konfiguration", "Options" => "Optionen", -"Applicable" => "Zutreffend", +"Available for" => "Verfügbar für", "Add storage" => "Speicher hinzufügen", -"None set" => "Nicht definiert", +"No user or group" => "Kein Nutzer oder Gruppe", "All Users" => "Alle Benutzer", "Groups" => "Gruppen", "Users" => "Benutzer", diff --git a/apps/files_external/l10n/de_CH.php b/apps/files_external/l10n/de_CH.php index 8a13c7cdd576320f4369803f89b5eeb56a2201e2..554fca8de545287af4c6128931508a4e32fde8b3 100644 --- a/apps/files_external/l10n/de_CH.php +++ b/apps/files_external/l10n/de_CH.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Zugriff gestatten", "Please provide a valid Dropbox app key and secret." => "Bitte tragen Sie einen gültigen Dropbox-App-Key mit Secret ein.", "Error configuring Google Drive storage" => "Fehler beim Einrichten von Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Warnung: «smbclient» ist nicht installiert. Das Einhängen von CIFS/SMB-Freigaben ist nicht möglich. Bitten Sie Ihren Systemadministrator, dies zu installieren.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Warnung:: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Bitte wenden Sie sich an Ihren Systemadministrator.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Achtung: Die Curl-Unterstützung von PHP ist nicht aktiviert oder installiert. Das Laden von ownCloud / WebDAV oder GoogleDrive Freigaben ist nicht möglich. Bitte Sie Ihren Systemadministrator, das Modul zu installieren.", "External Storage" => "Externer Speicher", "Folder name" => "Ordnername", "External storage" => "Externer Speicher", "Configuration" => "Konfiguration", "Options" => "Optionen", -"Applicable" => "Zutreffend", "Add storage" => "Speicher hinzufügen", -"None set" => "Nicht definiert", "All Users" => "Alle Benutzer", "Groups" => "Gruppen", "Users" => "Benutzer", diff --git a/apps/files_external/l10n/de_DE.php b/apps/files_external/l10n/de_DE.php index 5ffe946c699fbf252204e441ec74dbbafe9a246b..186aa5a299a568397542140d462aeadcb073cf50 100644 --- a/apps/files_external/l10n/de_DE.php +++ b/apps/files_external/l10n/de_DE.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Bitte tragen Sie einen gültigen Dropbox-App-Key mit Secret ein.", "Error configuring Google Drive storage" => "Fehler beim Einrichten von Google Drive", "Saved" => "Gespeichert", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Warnung: \"smbclient\" ist nicht installiert. Das Einhängen von CIFS/SMB-Freigaben ist nicht möglich. Bitten Sie Ihren Systemadministrator, dies zu installieren.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Warnung:: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Bitte wenden Sie sich an Ihren Systemadministrator.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Achtung: Die Curl-Unterstützung von PHP ist nicht aktiviert oder installiert. Das Laden von ownCloud / WebDAV oder GoogleDrive Freigaben ist nicht möglich. Bitte Sie Ihren Systemadministrator, das Modul zu installieren.", +"Note: " => "Hinweis: ", +" and " => "und", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Hinweis: Die cURL-Unterstützung von PHP ist nicht aktiviert oder installiert. Das Hinzufügen von %s ist nicht möglich. Bitte wenden Sie sich zur Installation an Ihren Systemadministrator.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Hinweis: Die FTP Unterstützung von PHP ist nicht aktiviert oder installiert. Das Hinzufügen von %s ist nicht möglich. Bitte wenden Sie sich zur Installation an Ihren Systemadministrator.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Hinweis: \"%s\" ist nicht installiert. Das Hinzufügen von %s ist nicht möglich. Bitte wenden Sie sich zur Installation an Ihren Systemadministrator.", "External Storage" => "Externer Speicher", "Folder name" => "Ordnername", "External storage" => "Externer Speicher", "Configuration" => "Konfiguration", "Options" => "Optionen", -"Applicable" => "Zutreffend", +"Available for" => "Verfügbar für", "Add storage" => "Speicher hinzufügen", -"None set" => "Nicht definiert", +"No user or group" => "Kein Nutzer oder Gruppe", "All Users" => "Alle Benutzer", "Groups" => "Gruppen", "Users" => "Benutzer", diff --git a/apps/files_external/l10n/el.php b/apps/files_external/l10n/el.php index 4dcd93d7ac8523dbb2ec0f8a6e3971b86b321ab4..16b837e24c5bd8f8373ca7974a9508aab9546c44 100644 --- a/apps/files_external/l10n/el.php +++ b/apps/files_external/l10n/el.php @@ -6,22 +6,18 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Παρακαλούμε δώστε έγκυρο κλειδί Dropbox και μυστικό.", "Error configuring Google Drive storage" => "Σφάλμα ρυθμίζωντας αποθήκευση Google Drive ", "Saved" => "Αποθηκεύτηκαν", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Προσοχή: Ο \"smbclient\" δεν εγκαταστάθηκε. Δεν είναι δυνατή η προσάρτηση CIFS/SMB. Παρακαλώ ενημερώστε τον διαχειριστή συστήματος να το εγκαταστήσει.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Προσοχή: Η υποστήριξη FTP στην PHP δεν ενεργοποιήθηκε ή εγκαταστάθηκε. Δεν είναι δυνατή η προσάρτηση FTP. Παρακαλώ ενημερώστε τον διαχειριστή συστήματος να το εγκαταστήσει.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "<Προειδοποίηση Η υποστήριξη του συστήματος Curl στο PHP δεν είναι ενεργοποιημένη ή εγκαταστημένη. Η αναπαραγωγή του ownCloud/WebDAV ή GoogleDrive δεν είναι δυνατή. Παρακαλώ ρωτήστε τον διαχειριστλη του συστήματος για την εγκατάσταση. ", "External Storage" => "Εξωτερικό Αποθηκευτικό Μέσο", "Folder name" => "Όνομα φακέλου", "External storage" => "Εξωτερική αποθήκευση", "Configuration" => "Ρυθμίσεις", "Options" => "Επιλογές", -"Applicable" => "Εφαρμόσιμο", "Add storage" => "Προσθηκη αποθηκευσης", -"None set" => "Κανένα επιλεγμένο", "All Users" => "Όλοι οι Χρήστες", "Groups" => "Ομάδες", "Users" => "Χρήστες", "Delete" => "Διαγραφή", "Enable User External Storage" => "Ενεργοποίηση Εξωτερικού Αποθηκευτικού Χώρου Χρήστη", +"Allow users to mount the following external storage" => "Χορήγηση άδειας στους χρήστες να συνδέσουν τα παρακάτω εξωτερικά μέσα αποθήκευσης", "SSL root certificates" => "Πιστοποιητικά SSL root", "Import Root Certificate" => "Εισαγωγή Πιστοποιητικού Root" ); diff --git a/apps/files_external/l10n/en_GB.php b/apps/files_external/l10n/en_GB.php index f7fdbf2f0d16cd7275b8cee7c99ce283e1a5c08d..4bd3f9daf2a8fc4fbdc8f53d17c51be60a9ddf90 100644 --- a/apps/files_external/l10n/en_GB.php +++ b/apps/files_external/l10n/en_GB.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Please provide a valid Dropbox app key and secret.", "Error configuring Google Drive storage" => "Error configuring Google Drive storage", "Saved" => "Saved", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it.", +"Note: " => "Note: ", +" and " => " and ", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it.", "External Storage" => "External Storage", "Folder name" => "Folder name", "External storage" => "External storage", "Configuration" => "Configuration", "Options" => "Options", -"Applicable" => "Applicable", +"Available for" => "Available for", "Add storage" => "Add storage", -"None set" => "None set", +"No user or group" => "No user or group", "All Users" => "All Users", "Groups" => "Groups", "Users" => "Users", diff --git a/apps/files_external/l10n/eo.php b/apps/files_external/l10n/eo.php index aba16e2efa8699bf1189218a19f7ac0184f6a07d..5312872c07a544c56aa2612d8642821e5b292d51 100644 --- a/apps/files_external/l10n/eo.php +++ b/apps/files_external/l10n/eo.php @@ -9,8 +9,6 @@ $TRANSLATIONS = array( "Folder name" => "Dosierujnomo", "Configuration" => "Agordo", "Options" => "Malneproj", -"Applicable" => "Aplikebla", -"None set" => "Nenio agordita", "All Users" => "Ĉiuj uzantoj", "Groups" => "Grupoj", "Users" => "Uzantoj", diff --git a/apps/files_external/l10n/es.php b/apps/files_external/l10n/es.php index ea831c947f44f0cdf6e33e6b41b69e5b80a8f4ed..bfe542c6e7123fc4519cc1e15ae297abad07e067 100644 --- a/apps/files_external/l10n/es.php +++ b/apps/files_external/l10n/es.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Por favor, proporcione un una clave válida de la app Dropbox y una clave secreta.", "Error configuring Google Drive storage" => "Error configurando el almacenamiento de Google Drive", "Saved" => "Guardado", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Advertencia: El cliente smb (smbclient) no se encuentra instalado. El montado de archivos o ficheros CIFS/SMB no es posible. Por favor pida al administrador de su sistema que lo instale.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Advertencia: El soporte de FTP en PHP no se encuentra instalado. El montado de archivos o ficheros FTP no es posible. Por favor pida al administrador de su sistema que lo instale.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Advertencia: El soporte de Curl en PHP no está activado ni instalado. El montado de ownCloud, WebDAV o GoogleDrive no es posible. Pida al administrador de su sistema que lo instale.", +"Note: " => "Nota: ", +" and " => "y", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: El soporte de cURL en PHP no está activado o instalado. No se puede montar %s. Pídale al administrador de sistema que lo instale.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: El soporte de FTP en PHP no está activado o instalado. No se puede montar %s. Pídale al administrador de sistema que lo instale.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: \"%s\" no está instalado. No se puede montar %s. Pídale al administrador de sistema que lo instale.", "External Storage" => "Almacenamiento externo", "Folder name" => "Nombre de la carpeta", "External storage" => "Almacenamiento externo", "Configuration" => "Configuración", "Options" => "Opciones", -"Applicable" => "Aplicable", +"Available for" => "Disponible para", "Add storage" => "Añadir almacenamiento", -"None set" => "No se ha configurado", +"No user or group" => "Ningún usuario o grupo", "All Users" => "Todos los usuarios", "Groups" => "Grupos", "Users" => "Usuarios", diff --git a/apps/files_external/l10n/es_AR.php b/apps/files_external/l10n/es_AR.php index 05204b748c4d584ee4f409da9624e94e525ec900..f184dbdb7d8aac91df20ff83fdcf0688d198a688 100644 --- a/apps/files_external/l10n/es_AR.php +++ b/apps/files_external/l10n/es_AR.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Permitir acceso", "Please provide a valid Dropbox app key and secret." => "Por favor, proporcioná un secreto y una contraseña válida para la aplicación Dropbox.", "Error configuring Google Drive storage" => "Error al configurar el almacenamiento de Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Advertencia: El cliente smb \"smbclient\" no está instalado. Montar archivos CIFS/SMB no es posible. Por favor, pedile al administrador de tu sistema que lo instale.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Advertencia: El soporte de FTP en PHP no está instalado. Montar archivos FTP no es posible. Por favor, pedile al administrador de tu sistema que lo instale.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Advertencia: El soporte de Curl de PHP no está activo ni instalado. Montar servicios ownCloud, WebDAV y/o GoogleDrive no será posible. Pedile al administrador del sistema que lo instale.", "External Storage" => "Almacenamiento externo", "Folder name" => "Nombre de la carpeta", "External storage" => "Almacenamiento externo", "Configuration" => "Configuración", "Options" => "Opciones", -"Applicable" => "Aplicable", "Add storage" => "Añadir almacenamiento", -"None set" => "No fue configurado", "All Users" => "Todos los usuarios", "Groups" => "Grupos", "Users" => "Usuarios", diff --git a/apps/files_external/l10n/es_MX.php b/apps/files_external/l10n/es_MX.php index 5d3fd44bec6947a2bf239dd049ce982f960e378f..dc0aef45c4f83ef7bda072aad6fb17203d9c950f 100644 --- a/apps/files_external/l10n/es_MX.php +++ b/apps/files_external/l10n/es_MX.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Conceder acceso", "Please provide a valid Dropbox app key and secret." => "Por favor, proporcione un una clave válida de la app Dropbox y una clave secreta.", "Error configuring Google Drive storage" => "Error configurando el almacenamiento de Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Advertencia: El cliente \"smbclient\" no se encuentra instalado. El montado de carpetas CIFS/SMB no es posible. Por favor pida al administrador de su sistema que lo instale.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Advertencia: El soporte de FTP en PHP no se encuentra instalado. El montado de carpetas FTP no es posible. Por favor pida al administrador de su sistema que lo instale.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Advertencia: El soporte de Curl en PHP no está activado ni instalado. El montado de ownCloud, WebDAV o GoogleDrive no es posible. Pida al administrador de su sistema que lo instale.", "External Storage" => "Almacenamiento externo", "Folder name" => "Nombre de la carpeta", "External storage" => "Almacenamiento externo", "Configuration" => "Configuración", "Options" => "Opciones", -"Applicable" => "Aplicable", "Add storage" => "Añadir almacenamiento", -"None set" => "No se ha configurado", "All Users" => "Todos los usuarios", "Groups" => "Grupos", "Users" => "Usuarios", diff --git a/apps/files_external/l10n/et_EE.php b/apps/files_external/l10n/et_EE.php index c6450f95e183caed166c85e1c47901742d3492ab..0589d9fd518c2bbbea6b0db79b97b48671e48bee 100644 --- a/apps/files_external/l10n/et_EE.php +++ b/apps/files_external/l10n/et_EE.php @@ -5,22 +5,21 @@ $TRANSLATIONS = array( "Grant access" => "Anna ligipääs", "Please provide a valid Dropbox app key and secret." => "Palun sisesta korrektne Dropboxi rakenduse võti ja salasõna.", "Error configuring Google Drive storage" => "Viga Google Drive'i salvestusruumi seadistamisel", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Hoiatus: \"smbclient\" pole paigaldatud. Jagatud CIFS/SMB hoidlate ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata SAMBA tugi.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Hoiatus: PHP-s puudub FTP tugi. Jagatud FTP hoidlate ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata FTP tugi.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Hoiatus: PHP-s puudub Curl tugi. Jagatud ownCloud / WebDAV või GoogleDrive ühendamine pole võimalik. Palu oma süsteemihalduril see paigaldada.", +"Saved" => "Salvestatud", "External Storage" => "Väline salvestuskoht", "Folder name" => "Kausta nimi", "External storage" => "Väline andmehoidla", "Configuration" => "Seadistamine", "Options" => "Valikud", -"Applicable" => "Rakendatav", +"Available for" => "Saadaval", "Add storage" => "Lisa andmehoidla", -"None set" => "Pole määratud", +"No user or group" => "Ühtki kasutajat või gruppi", "All Users" => "Kõik kasutajad", "Groups" => "Grupid", "Users" => "Kasutajad", "Delete" => "Kustuta", "Enable User External Storage" => "Luba kasutajatele väline salvestamine", +"Allow users to mount the following external storage" => "Võimalda kasutajatel ühendada järgmist välist andmehoidlat", "SSL root certificates" => "SSL root sertifikaadid", "Import Root Certificate" => "Impordi root sertifikaadid" ); diff --git a/apps/files_external/l10n/eu.php b/apps/files_external/l10n/eu.php index bdc5cf56760139330fdab4d71fdd1babac2361ce..c2111a1f73630f03b69965a0d4de1d4a3f5e4032 100644 --- a/apps/files_external/l10n/eu.php +++ b/apps/files_external/l10n/eu.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Baimendu sarrera", "Please provide a valid Dropbox app key and secret." => "Mesedez eman baliozkoa den Dropbox app giltza eta sekretua", "Error configuring Google Drive storage" => "Errore bat egon da Google Drive biltegiratzea konfiguratzean", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Abisua: \"smbclient\" ez dago instalatuta. CIFS/SMB partekatutako karpetak montatzea ez da posible. Mesedez eskatu zure sistema kudeatzaileari instalatzea.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Abisua: PHPren FTP modulua ez dago instalatuta edo gaitua. FTP partekatutako karpetak montatzea ez da posible. Mesedez eskatu zure sistema kudeatzaileari instalatzea.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Abisua: Curl euskarri PHP modulua ez dago instalatuta edo gaitua. Ezinezko da ownCloud /WebDAV GoogleDrive-n muntatzea. Mesedez eskatu sistema kudeatzaileari instala dezan. ", "External Storage" => "Kanpoko Biltegiratzea", "Folder name" => "Karpetaren izena", "External storage" => "Kanpoko biltegiratzea", "Configuration" => "Konfigurazioa", "Options" => "Aukerak", -"Applicable" => "Aplikagarria", "Add storage" => "Gehitu biltegiratzea", -"None set" => "Ezarri gabe", "All Users" => "Erabiltzaile guztiak", "Groups" => "Taldeak", "Users" => "Erabiltzaileak", diff --git a/apps/files_external/l10n/fa.php b/apps/files_external/l10n/fa.php index 544b8a14d5cdc6a7ab623ecb9b0489370855d4fe..74472c54bf53d3ebda236bb5ae53e7896817eac0 100644 --- a/apps/files_external/l10n/fa.php +++ b/apps/files_external/l10n/fa.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => " مجوز اعطا دسترسی", "Please provide a valid Dropbox app key and secret." => "لطفا یک کلید و کد امنیتی صحیح دراپ باکس وارد کنید.", "Error configuring Google Drive storage" => "خطا به هنگام تنظیم فضای Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "خطا: \"smbclient\" نصب نشده است. نصب و راه اندازی سهام CIFS/SMB امکان پذیر نمیباشد. لطفا از مدیریت سازمان خود برای راه اندازی آن درخواست نمایید.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "خطا: پشتیبانی FTP در PHP فعال نمی باشد یا نصب نشده است. نصب و راه اندازی از سهم های FTP امکان پذیر نمی باشد. لطفا از مدیر سیستم خود برای راه اندازی آن درخواست\nکنید.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "خطا: پشتیبانی Curl فعال نمی باشد یا نصب نشده است. نصب و راه اندازی ownCloud / WebDAV یا GoogleDrive امکان پذیر نیست. لطفا از مدیر سیستم خود برای نصب آن درخواست کنید.", "External Storage" => "حافظه خارجی", "Folder name" => "نام پوشه", "External storage" => "حافظه خارجی", "Configuration" => "پیکربندی", "Options" => "تنظیمات", -"Applicable" => "قابل اجرا", "Add storage" => "اضافه کردن حافظه", -"None set" => "تنظیم نشده", "All Users" => "تمام کاربران", "Groups" => "گروه ها", "Users" => "کاربران", diff --git a/apps/files_external/l10n/fi_FI.php b/apps/files_external/l10n/fi_FI.php index d2f9d1a73a5ad0f3501029ef99356e2c16dfa4b5..677425d8a6a945cc5a29972718fe4c454ed7ee69 100644 --- a/apps/files_external/l10n/fi_FI.php +++ b/apps/files_external/l10n/fi_FI.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Anna kelvollinen Dropbox-sovellusavain ja salainen vastaus.", "Error configuring Google Drive storage" => "Virhe Google Drive levyn asetuksia tehtäessä", "Saved" => "Tallennettu", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Varoitus: \"smbclient\" ei ole asennettuna. CIFS-/SMB-jakojen liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää asentamaan smbclient.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Varoitus: PHP:n FTP-tuki ei ole käytössä tai sitä ei ole asennettu. FTP-jakojen liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan FTP-tuki käyttöön.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Varoitus: PHP:n Curl-tuki ei ole käytössä tai sitä ei ole lainkaan asennettu. ownCloudin, WebDAV:in tai Google Driven liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan Curl-tuki käyttöön.", +"Note: " => "Huomio: ", +" and " => "ja", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Huomio: PHP:n cURL-tuki ei ole käytössä tai sitä ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan cURL-tuki käyttöön.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Huomio: PHP:n FTP-tuki ei ole käytössä tai sitä ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää ottamaan FTP-tuki käyttöön.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Huomio: \"%s\" ei ole asennettu. Kohteen %s liittäminen ei ole mahdollista. Pyydä järjestelmän ylläpitäjää asentamaan puuttuva kohde.", "External Storage" => "Erillinen tallennusväline", "Folder name" => "Kansion nimi", "External storage" => "Ulkoinen tallennustila", "Configuration" => "Asetukset", "Options" => "Valinnat", -"Applicable" => "Sovellettavissa", +"Available for" => "Saatavuus", "Add storage" => "Lisää tallennustila", -"None set" => "Ei asetettu", +"No user or group" => "Ei käyttäjää tai ryhmää", "All Users" => "Kaikki käyttäjät", "Groups" => "Ryhmät", "Users" => "Käyttäjät", diff --git a/apps/files_external/l10n/fr.php b/apps/files_external/l10n/fr.php index 4b8e2b905b6ffe0cff2942559edb8f7f06926cd0..8ff1969718217b2a403d718e88fabe2e4a4b1fdd 100644 --- a/apps/files_external/l10n/fr.php +++ b/apps/files_external/l10n/fr.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Veuillez fournir une clé d'application (app key) ainsi qu'un mot de passe valides.", "Error configuring Google Drive storage" => "Erreur lors de la configuration du support de stockage Google Drive", "Saved" => "Sauvegarder", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Attention : \"smbclient\" n'est pas installé. Le montage des partages CIFS/SMB n'est pas disponible. Contactez votre administrateur système pour l'installer.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Attention : Le support FTP de PHP n'est pas activé ou installé. Le montage des partages FTP n'est pas disponible. Contactez votre administrateur système pour l'installer.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Attention : Le support de Curl n'est pas activé ou installé dans PHP. Le montage de ownCloud / WebDAV ou GoogleDrive n'est pas possible. Contactez votre administrateur système pour l'installer.", +"Note: " => "Attention :", +" and " => "et", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Attention : Le support de cURL de PHP n'est pas activé ou installé. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Attention : Le support FTP de PHP n'est pas activé ou installé. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Attention : \"%s\" n'est pas installé. Le montage de %s n'est pas possible. Contactez votre administrateur système pour l'installer.", "External Storage" => "Stockage externe", "Folder name" => "Nom du dossier", "External storage" => "Stockage externe", "Configuration" => "Configuration", "Options" => "Options", -"Applicable" => "Disponible", +"Available for" => "Disponible pour", "Add storage" => "Ajouter un support de stockage", -"None set" => "Aucun spécifié", +"No user or group" => "Aucun utilisateur ou groupe", "All Users" => "Tous les utilisateurs", "Groups" => "Groupes", "Users" => "Utilisateurs", diff --git a/apps/files_external/l10n/gl.php b/apps/files_external/l10n/gl.php index ec13fe241f603db561638ee74db8fe194bfa0a31..5efa6ce6028b77766231917e4c4a8d4dd355bae9 100644 --- a/apps/files_external/l10n/gl.php +++ b/apps/files_external/l10n/gl.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Forneza unha chave correcta e segreda do Dropbox.", "Error configuring Google Drive storage" => "Produciuse un erro ao configurar o almacenamento en Google Drive", "Saved" => "Gardado", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Aviso: «smbclient» non está instalado. Non é posibel a montaxe de comparticións CIFS/SMB. Consulte co administrador do sistema para instalalo.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Aviso: A compatibilidade de FTP en PHP non está activada ou instalada. Non é posibel a montaxe de comparticións FTP. Consulte co administrador do sistema para instalalo.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Aviso: A compatibilidade de Curl en PHP non está activada ou instalada. Non é posíbel a montaxe de ownCloud / WebDAV ou GoogleDrive. Consulte co administrador do sistema para instalala.", +"Note: " => "Nota: ", +" and " => "e", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: A compatibilidade de cURL en PHP non está activada, ou non está instalado. Non é posíbel a montaxe de %s. Consulte co administrador do sistema como instalalo.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: A compatibilidade de FTP en PHP non está activada, ou non está instalado. Non é posíbel a montaxe de %s. Consulte co administrador do sistema como instalalo.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: «%s» non está instalado. Non é posíbel a montaxe de %s. Consulte co administrador do sistema como instalalo.", "External Storage" => "Almacenamento externo", "Folder name" => "Nome do cartafol", "External storage" => "Almacenamento externo", "Configuration" => "Configuración", "Options" => "Opcións", -"Applicable" => "Aplicábel", +"Available for" => "Dispoñíbel para", "Add storage" => "Engadir almacenamento", -"None set" => "Ningún definido", +"No user or group" => "Non hai usuario ou grupo", "All Users" => "Todos os usuarios", "Groups" => "Grupos", "Users" => "Usuarios", diff --git a/apps/files_external/l10n/he.php b/apps/files_external/l10n/he.php index 6aec07e78cf9725d0e0198c763368697630a82d1..e433f4fc3068ced6f106380697fcc68f23333ab5 100644 --- a/apps/files_external/l10n/he.php +++ b/apps/files_external/l10n/he.php @@ -9,8 +9,6 @@ $TRANSLATIONS = array( "Folder name" => "שם התיקייה", "Configuration" => "הגדרות", "Options" => "אפשרויות", -"Applicable" => "ניתן ליישום", -"None set" => "לא הוגדרה", "All Users" => "כל המשתמשים", "Groups" => "קבוצות", "Users" => "משתמשים", diff --git a/apps/files_external/l10n/hu_HU.php b/apps/files_external/l10n/hu_HU.php index 6066138043386c714e7a3111ffc9f554138d82af..39d185d5f0b53fdbc5f2941cc457aad1099461f8 100644 --- a/apps/files_external/l10n/hu_HU.php +++ b/apps/files_external/l10n/hu_HU.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Megadom a hozzáférést", "Please provide a valid Dropbox app key and secret." => "Adjon meg egy érvényes Dropbox app key-t és secretet!", "Error configuring Google Drive storage" => "A Google Drive tárolót nem sikerült beállítani", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Figyelem: az \"smbclient\" nincs telepítve a kiszolgálón. Emiatt nem lehet CIFS/SMB megosztásokat fölcsatolni. Kérje meg a rendszergazdát, hogy telepítse a szükséges programot.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Figyelem: a PHP FTP támogatása vagy nincs telepítve, vagy nincs engedélyezve a kiszolgálón. Emiatt nem lehetséges FTP-tárolókat fölcsatolni. Kérje meg a rendszergazdát, hogy telepítse a szükséges programot.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Figyelmeztetés: A PHP-ben nincs telepítve vagy engedélyezve a Curl támogatás. Nem lehetséges ownCloud / WebDAV ill. GoogleDrive tárolók becsatolása. Kérje meg a rendszergazdát, hogy telepítse a szükséges programot!", "External Storage" => "Külső tárolási szolgáltatások becsatolása", "Folder name" => "Mappanév", "External storage" => "Külső tárolók", "Configuration" => "Beállítások", "Options" => "Opciók", -"Applicable" => "Érvényességi kör", "Add storage" => "Tároló becsatolása", -"None set" => "Nincs beállítva", "All Users" => "Az összes felhasználó", "Groups" => "Csoportok", "Users" => "Felhasználók", diff --git a/apps/files_external/l10n/id.php b/apps/files_external/l10n/id.php index 9f91fdf992f48e05d74ae55f507477f4c2b596b4..8ab5069539fcd809a282bd204549f24b83d0a69f 100644 --- a/apps/files_external/l10n/id.php +++ b/apps/files_external/l10n/id.php @@ -5,16 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Berikan hak akses", "Please provide a valid Dropbox app key and secret." => "Masukkan kunci dan sandi aplikasi Dropbox yang benar.", "Error configuring Google Drive storage" => "Kesalahan dalam mengkonfigurasi penyimpanan Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Peringatan: \"smbclient\" tidak terpasang. Mount direktori CIFS/SMB tidak dapat dilakukan. Silakan minta administrator sistem untuk memasangnya.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Peringatan: Dukungan FTP di PHP tidak aktif atau tidak terpasang. Mount direktori FTP tidak dapat dilakukan. Silakan minta administrator sistem untuk memasangnya.", "External Storage" => "Penyimpanan Eksternal", "Folder name" => "Nama folder", "External storage" => "Penyimpanan eksternal", "Configuration" => "Konfigurasi", "Options" => "Opsi", -"Applicable" => "Berlaku", "Add storage" => "Tambahkan penyimpanan", -"None set" => "Tidak satupun di set", "All Users" => "Semua Pengguna", "Groups" => "Grup", "Users" => "Pengguna", diff --git a/apps/files_external/l10n/is.php b/apps/files_external/l10n/is.php index e86cfa108a63bfc85df62b8c809f68622456a25e..21a215807abcbb68e2b7d1a3bd6de6cab1834838 100644 --- a/apps/files_external/l10n/is.php +++ b/apps/files_external/l10n/is.php @@ -5,14 +5,10 @@ $TRANSLATIONS = array( "Grant access" => "Veita aðgengi", "Please provide a valid Dropbox app key and secret." => "Gefðu upp virkan Dropbox lykil og leynikóða", "Error configuring Google Drive storage" => "Villa kom upp við að setja upp Google Drive gagnasvæði", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Aðvörun: \"smbclient\" er ekki uppsettur. Uppsetning á CIFS/SMB gagnasvæðum er ekki möguleg. Hafðu samband við kerfisstjóra til að fá hann uppsettan.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Aðvörun: FTP stuðningur í PHP er ekki virkur. Uppsetning á FTP gagnasvæðum er ekki möguleg. Hafðu samband við kerfisstjóra til að fá hann uppsettan.", "External Storage" => "Ytri gagnageymsla", "Folder name" => "Nafn möppu", "Configuration" => "Uppsetning", "Options" => "Stillingar", -"Applicable" => "Gilt", -"None set" => "Ekkert sett", "All Users" => "Allir notendur", "Groups" => "Hópar", "Users" => "Notendur", diff --git a/apps/files_external/l10n/it.php b/apps/files_external/l10n/it.php index d62d8e973274eee23eb1337f9ef33e3dfa70e4c2..f3a6f9af12936dc23fd7d868c4e6eef988e1747b 100644 --- a/apps/files_external/l10n/it.php +++ b/apps/files_external/l10n/it.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Fornisci chiave di applicazione e segreto di Dropbox validi.", "Error configuring Google Drive storage" => "Errore durante la configurazione dell'archivio Google Drive", "Saved" => "Salvato", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Avviso: \"smbclient\" non è installato. Impossibile montare condivisioni CIFS/SMB. Chiedi all'amministratore di sistema di installarlo.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Avviso: il supporto FTP di PHP non è abilitato o non è installato. Impossibile montare condivisioni FTP. Chiedi all'amministratore di sistema di installarlo.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Avviso: il supporto Curl di PHP non è abilitato o non è installato. Impossibile montare condivisioni ownCloud / WebDAV o GoogleDrive. Chiedi all'amministratore di sistema di installarlo.", +"Note: " => "Nota:", +" and " => "e", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: il supporto a cURL di PHP non è abilitato o installato. Impossibile montare %s. Chiedi al tuo amministratore di sistema di installarlo.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: il supporto a FTP in PHP non è abilitato o installato. Impossibile montare %s. Chiedi al tuo amministratore di sistema di installarlo.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: \"%s\" non è installato. Impossibile montare %s. Chiedi al tuo amministratore di sistema di installarlo.", "External Storage" => "Archiviazione esterna", "Folder name" => "Nome della cartella", "External storage" => "Archiviazione esterna", "Configuration" => "Configurazione", "Options" => "Opzioni", -"Applicable" => "Applicabile", +"Available for" => "Disponibile per", "Add storage" => "Aggiungi archiviazione", -"None set" => "Nessuna impostazione", +"No user or group" => "Nessun utente o gruppo", "All Users" => "Tutti gli utenti", "Groups" => "Gruppi", "Users" => "Utenti", diff --git a/apps/files_external/l10n/ja.php b/apps/files_external/l10n/ja.php index 312dc85188dd572d9103cc10fe5257283266437a..52d66043e1947d4f948c13fd44daceb6dff868ef 100644 --- a/apps/files_external/l10n/ja.php +++ b/apps/files_external/l10n/ja.php @@ -6,17 +6,13 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "有効なDropboxアプリのキーとパスワードを入力してください。", "Error configuring Google Drive storage" => "Googleドライブストレージの設定エラー", "Saved" => "保存されました", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "警告: \"smbclient\" がインストールされていません。CIFS/SMB共有のマウントはできません。システム管理者にインストールを依頼してください。", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "警告: PHPのFTPサポートが無効またはインストールされていません。FTP共有のマウントはできません。システム管理者にインストールを依頼してください。", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "警告: PHPのCurlサポートが無効またはインストールされていません。ownCloud / WebDAVまたはGoogleDriveのマウントはできません。システム管理者にインストールを依頼してください。", "External Storage" => "外部ストレージ", "Folder name" => "フォルダー名", "External storage" => "外部ストレージ", "Configuration" => "設定", "Options" => "オプション", -"Applicable" => "適用範囲", "Add storage" => "ストレージを追加", -"None set" => "未設定", +"No user or group" => "ユーザーもしくはグループがありません", "All Users" => "すべてのユーザー", "Groups" => "グループ", "Users" => "ユーザー", diff --git a/apps/files_external/l10n/ka_GE.php b/apps/files_external/l10n/ka_GE.php index 4953f91ce6a9540f3cfec793803ad5a92d90e1f1..d68dae88c029aa437fe274f05a1df2a3d0dbc752 100644 --- a/apps/files_external/l10n/ka_GE.php +++ b/apps/files_external/l10n/ka_GE.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "დაშვების მინიჭება", "Please provide a valid Dropbox app key and secret." => "გთხოვთ მიუთითოთ Dropbox აპლიკაციის გასაღები და კოდი.", "Error configuring Google Drive storage" => "შეცდომა Google Drive საცავის კონფიგურირების დროს", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "გაფრთხილება: \"smbclient\" არ არის ინსტალირებული. CIFS/SMB ზიარების მონტირება შეუძლებელია. გთხოვთ თხოვოთ თქვენს სისტემურ ადმინისტრატორებს დააინსტალიროს ის.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "გაფრთხილება: FTP მხარდაჭერა არ არის აქტიური ან დაინსტალირებული. FTP ზიარის მონტირება შეუძლებელია. გთხოვთ თხოვოთ თქვენს სისტემურ ადმინისტრატორებს დააინსტალიროს ის.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "გაფრთხილება:PHP–ის Curl მხარდაჭერა არ არის ჩართული ან ინსტალირებული. ownCloud / WebDAV ან GoogleDrive–ის მონტირება შეუძლებელია. თხოვეთ თქვენს ადმინისტრატორს დააინსტალიროს ის.", "External Storage" => "ექსტერნალ საცავი", "Folder name" => "ფოლდერის სახელი", "External storage" => "ექსტერნალ საცავი", "Configuration" => "კონფიგურაცია", "Options" => "ოფცია", -"Applicable" => "მიღებადი", "Add storage" => "საცავის დამატება", -"None set" => "არაფერია მითითებული", "All Users" => "ყველა მომხმარებელი", "Groups" => "ჯგუფები", "Users" => "მომხმარებელი", diff --git a/apps/files_external/l10n/km.php b/apps/files_external/l10n/km.php index 4586f866a7453b122bd719ef403e70c3edeb658f..75879f2300e1652263d539dce01556afd4958d56 100644 --- a/apps/files_external/l10n/km.php +++ b/apps/files_external/l10n/km.php @@ -1,6 +1,7 @@ "ឈ្មោះ​ថត", +"Options" => "ជម្រើស", "Groups" => "ក្រុ", "Users" => "អ្នកប្រើ", "Delete" => "លុប" diff --git a/apps/files_external/l10n/ko.php b/apps/files_external/l10n/ko.php index 088a419e1c1166c47aa2cc17f74e1107fc2a1185..371cba3e12d89cff2e45d6c596664b1cc32838f3 100644 --- a/apps/files_external/l10n/ko.php +++ b/apps/files_external/l10n/ko.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "접근 권한 부여", "Please provide a valid Dropbox app key and secret." => "올바른 Dropbox 앱 키와 암호를 입력하십시오.", "Error configuring Google Drive storage" => "Google 드라이브 저장소 설정 오류", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "경고: \"smbclient\"가 설치되지 않았습니다. CIFS/SMB 공유 자원에 연결할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "경고: PHP FTP 지원이 비활성화되어 있거나 설치되지 않았습니다. FTP 공유를 마운트할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "경고: PHP Curl 지원이 비활성화되어 있거나 설치되지 않았습니다. 다른 ownCloud, WebDAV, Google 드라이브 공유를 마운트할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", "External Storage" => "외부 저장소", "Folder name" => "폴더 이름", "External storage" => "외부 저장소", "Configuration" => "설정", "Options" => "옵션", -"Applicable" => "적용 가능", "Add storage" => "저장소 추가", -"None set" => "설정되지 않음", "All Users" => "모든 사용자", "Groups" => "그룹", "Users" => "사용자", diff --git a/apps/files_external/l10n/lt_LT.php b/apps/files_external/l10n/lt_LT.php index c96119c8b68238fcaffa06927c7ba10b16bc3d4b..fdf1ee70136b75994f0856134adb6e2c84b9b4c3 100644 --- a/apps/files_external/l10n/lt_LT.php +++ b/apps/files_external/l10n/lt_LT.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Suteikti priėjimą", "Please provide a valid Dropbox app key and secret." => "Prašome įvesti teisingus Dropbox \"app key\" ir \"secret\".", "Error configuring Google Drive storage" => "Klaida nustatinėjant Google Drive talpyklą", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Įspėjimas: \"smbclient\" nėra įdiegtas. CIFS/SMB dalinimasis nėra galimas. Prašome susisiekti su sistemos administratoriumi kad būtų įdiegtas \"smbclient\"", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Įspėjimas: FTP palaikymas PHP sistemoje nėra įjungtas arba nėra įdiegtas. FTP dalinimosi įjungimas nėra galimas. Prašome susisiekti su sistemos administratoriumi kad būtų įdiegtas FTP palaikymas. ", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Įspėjimas: \"Curl\" palaikymas PHP terpėje nėra įjungtas arba įdiegtas. ownCloud/WebDAV ar GoogleDrive įjungimas nebus įmanomas. Prašome susisiekti su sistemos administratoriumi kad būtų įdiegtas arba įjungtas \"Curl\" palaikymas.", "External Storage" => "Išorinės saugyklos", "Folder name" => "Katalogo pavadinimas", "External storage" => "Išorinė saugykla", "Configuration" => "Konfigūracija", "Options" => "Nustatymai", -"Applicable" => "Pritaikyti", "Add storage" => "Pridėti saugyklą", -"None set" => "Nieko nepasirinkta", "All Users" => "Visi vartotojai", "Groups" => "Grupės", "Users" => "Vartotojai", diff --git a/apps/files_external/l10n/lv.php b/apps/files_external/l10n/lv.php index 18e56178892793e25c94b8aebb7ae4ea9733b7e4..e1037b503286f85687ea235cc30f18441e237cc7 100644 --- a/apps/files_external/l10n/lv.php +++ b/apps/files_external/l10n/lv.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Piešķirt pieeju", "Please provide a valid Dropbox app key and secret." => "Lūdzu, norādiet derīgu Dropbox lietotnes atslēgu un noslēpumu.", "Error configuring Google Drive storage" => "Kļūda, konfigurējot Google Drive krātuvi", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Brīdinājums: nav uzinstalēts “smbclient”. Nevar montēt CIFS/SMB koplietojumus. Lūdzu, vaicājiet savam sistēmas administratoram, lai to uzinstalē.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Brīdinājums: uz PHP nav aktivēts vai instalēts FTP atbalsts. Nevar montēt FTP koplietojumus. Lūdzu, vaicājiet savam sistēmas administratoram, lai to uzinstalē.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Brīdinājums: PHP Curl atbalsts nav instalēts. OwnCloud / WebDAV vai GoogleDrive montēšana nav iespējama. Lūdziet sistēmas administratoram lai tas tiek uzstādīts.", "External Storage" => "Ārējā krātuve", "Folder name" => "Mapes nosaukums", "External storage" => "Ārējā krātuve", "Configuration" => "Konfigurācija", "Options" => "Opcijas", -"Applicable" => "Piemērojams", "Add storage" => "Pievienot krātuvi", -"None set" => "Neviens nav iestatīts", "All Users" => "Visi lietotāji", "Groups" => "Grupas", "Users" => "Lietotāji", diff --git a/apps/files_external/l10n/mk.php b/apps/files_external/l10n/mk.php index b59bb138f1da07deef38185c7e632df745fbba05..507c0a745593baffcf86f77088d6692f1b7fc89b 100644 --- a/apps/files_external/l10n/mk.php +++ b/apps/files_external/l10n/mk.php @@ -5,14 +5,10 @@ $TRANSLATIONS = array( "Grant access" => "Дозволи пристап", "Please provide a valid Dropbox app key and secret." => "Ве молам доставите валиден Dropbox клуч и тајна лозинка.", "Error configuring Google Drive storage" => "Грешка при конфигурација на Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Внимание: \"smbclient\" не е инсталиран. Не е можно монтирање на CIFS/SMB дискови. Замолете го Вашиот систем администратор да го инсталира.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Внимание: Не е овозможена или инсталирани FTP подршка во PHP. Не е можно монтирање на FTP дискови. Замолете го Вашиот систем администратор да го инсталира.", "External Storage" => "Надворешно складиште", "Folder name" => "Име на папка", "Configuration" => "Конфигурација", "Options" => "Опции", -"Applicable" => "Применливо", -"None set" => "Ништо поставено", "All Users" => "Сите корисници", "Groups" => "Групи", "Users" => "Корисници", diff --git a/apps/files_external/l10n/nb_NO.php b/apps/files_external/l10n/nb_NO.php index c103112dbe3f271e9c81effcdb90ebf4e3b97ad9..95c9b47f412c12e69f0a6b3fcd602736f4f0dca2 100644 --- a/apps/files_external/l10n/nb_NO.php +++ b/apps/files_external/l10n/nb_NO.php @@ -5,17 +5,13 @@ $TRANSLATIONS = array( "Grant access" => "Gi tilgang", "Please provide a valid Dropbox app key and secret." => "Vær vennlig å oppgi gyldig Dropbox appnøkkel og hemmelighet.", "Error configuring Google Drive storage" => "Feil med konfigurering av Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Advarsel: \"smbclient\" er ikke installert. Kan ikke montere CIFS/SMB mapper. Ta kontakt med din systemadministrator for å installere det.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Advarsel: FTP støtte i PHP er ikke slått på eller innstallert. Kan ikke montere FTP mapper. Ta kontakt med din systemadministrator for å innstallere det.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Advarsel: Curl støtte i PHP er ikke aktivert eller innstallert. Kan ikke montere owncloud/WebDAV eller Googledrive. Ta kontakt med din systemadministrator for å innstallerer det.", +"Saved" => "Lagret", "External Storage" => "Ekstern lagring", "Folder name" => "Mappenavn", "External storage" => "Ekstern lagringsplass", "Configuration" => "Konfigurasjon", "Options" => "Innstillinger", -"Applicable" => "Anvendelig", "Add storage" => "Legg til lagringsplass", -"None set" => "Ingen valgt", "All Users" => "Alle brukere", "Groups" => "Grupper", "Users" => "Brukere", diff --git a/apps/files_external/l10n/nl.php b/apps/files_external/l10n/nl.php index 4fa579775f96e0a93e1e69605a13de781a871844..c055be50f8786758713dfe0965787de6231dd8a2 100644 --- a/apps/files_external/l10n/nl.php +++ b/apps/files_external/l10n/nl.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Geef een geldige Dropbox key en secret.", "Error configuring Google Drive storage" => "Fout tijdens het configureren van Google Drive opslag", "Saved" => "Bewaard", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Waarschuwing: \"smbclient\" is niet geïnstalleerd. Mounten van CIFS/SMB shares is niet mogelijk. Vraag uw beheerder om smbclient te installeren.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Waarschuwing: FTP ondersteuning in PHP is niet geactiveerd of geïnstalleerd. Mounten van FTP shares is niet mogelijk. Vraag uw beheerder FTP ondersteuning te installeren.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Waarschuwing: Curl ondersteuning in PHP is niet geactiveerd of geïnstalleerd. Mounten van ownCloud / WebDAV of GoogleDrive is niet mogelijk. Vraag uw systeembeheerder dit te installeren.", +"Note: " => "Let op: ", +" and " => "en", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Let op: Curl ondersteuning in PHP is niet geactiveerd of geïnstalleerd. Mounten van %s is niet mogelijk. Vraag uw systeembeheerder dit te installeren.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Let op: FTP ondersteuning in PHP is niet geactiveerd of geïnstalleerd. Mounten van %s is niet mogelijk. Vraag uw beheerder dit te installeren.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Let op: \"%s\" is niet geïnstalleerd. Mounten van %s is niet mogelijk. Vraag uw beheerder om dit te installeren.", "External Storage" => "Externe opslag", "Folder name" => "Mapnaam", "External storage" => "Externe opslag", "Configuration" => "Configuratie", "Options" => "Opties", -"Applicable" => "Van toepassing", +"Available for" => "Beschikbaar voor", "Add storage" => "Toevoegen opslag", -"None set" => "Niets ingesteld", +"No user or group" => "Geen gebruiker of groep", "All Users" => "Alle gebruikers", "Groups" => "Groepen", "Users" => "Gebruikers", diff --git a/apps/files_external/l10n/pl.php b/apps/files_external/l10n/pl.php index ece0620f754bf27b26f6b5545bf6161cab75d288..246e12b6ac8f209ef596d4527e23b128ece6aa45 100644 --- a/apps/files_external/l10n/pl.php +++ b/apps/files_external/l10n/pl.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Proszę podać prawidłowy klucz aplikacji Dropbox i klucz sekretny.", "Error configuring Google Drive storage" => "Wystąpił błąd podczas konfigurowania zasobu Google Drive", "Saved" => "Zapisano", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Ostrzeżenie: \"smbclient\" nie jest zainstalowany. Zamontowanie katalogów CIFS/SMB nie jest możliwe. Skontaktuj sie z administratorem w celu zainstalowania.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Ostrzeżenie: Wsparcie dla FTP w PHP nie jest zainstalowane lub włączone. Skontaktuj sie z administratorem w celu zainstalowania lub włączenia go.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Ostrzeżenie: Wsparcie dla Curl w PHP nie jest zainstalowane lub włączone. Montowanie WebDAV lub GoogleDrive nie będzie możliwe. Skontaktuj się z administratorem w celu zainstalowania lub włączenia tej opcji.", +"Note: " => "Uwaga: ", +" and " => "oraz", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Uwaga: Wsparcie dla cURL w PHP nie zostało włączone lub zainstalowane. Zamontowanie %s nie jest możliwe. Proszę poproś Twojego administratora o zainstalowanie go.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Uwaga: Wsparcie dla FTP w PHP nie zostało włączone lub zainstalowane. Zamontowanie %s nie jest możliwe. Proszę poproś Twojego administratora o zainstalowanie go.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Uwaga: \"%s\" nie jest zainstalowane. Zamontowanie %s nie jest możliwe. Proszę poproś Twojego administratora o zainstalowanie go.", "External Storage" => "Zewnętrzna zasoby dyskowe", "Folder name" => "Nazwa folderu", "External storage" => "Zewnętrzne zasoby dyskowe", "Configuration" => "Konfiguracja", "Options" => "Opcje", -"Applicable" => "Zastosowanie", +"Available for" => "Dostępne przez", "Add storage" => "Dodaj zasoby dyskowe", -"None set" => "Nie ustawione", +"No user or group" => "Brak użytkownika lub grupy", "All Users" => "Wszyscy uzytkownicy", "Groups" => "Grupy", "Users" => "Użytkownicy", diff --git a/apps/files_external/l10n/pt_BR.php b/apps/files_external/l10n/pt_BR.php index fbb945c54392220594efe00a386791350f615256..9a5a39f2358595e58fe65703a3df80b49259cf3c 100644 --- a/apps/files_external/l10n/pt_BR.php +++ b/apps/files_external/l10n/pt_BR.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Por favor forneça um app key e secret válido do Dropbox", "Error configuring Google Drive storage" => "Erro ao configurar armazenamento do Google Drive", "Saved" => "Salvo", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Aviso: \"smbclient\" não está instalado. Impossível montar compartilhamentos de CIFS/SMB. Por favor, peça ao seu administrador do sistema para instalá-lo.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Aviso: O suporte para FTP do PHP não está ativado ou instalado. Impossível montar compartilhamentos FTP. Por favor, peça ao seu administrador do sistema para instalá-lo.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => " Aviso: O suport a Curl em PHP não está habilitado ou instalado. A montagem do ownCloud / WebDAV ou GoogleDrive não é possível. Por favor, solicite ao seu administrador do sistema instalá-lo.", +"Note: " => "Nota:", +" and " => "e", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: O suporte cURL do PHP não está habilitado ou instalado. Montagem de %s não é possível. Por favor, solicite ao seu administrador do sistema para instalá-lo.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: O suporte FTP no PHP não está habilitado ou instalado. Montagem de %s não é possível. Por favor, solicite ao seu administrador do sistema para instalá-lo.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: \"%s\" não está instalado. Montagem de %s não é possível. Por favor, solicite ao seu administrador do sistema para instalá-lo.", "External Storage" => "Armazenamento Externo", "Folder name" => "Nome da pasta", "External storage" => "Armazenamento Externo", "Configuration" => "Configuração", "Options" => "Opções", -"Applicable" => "Aplicável", +"Available for" => "Disponível para", "Add storage" => "Adicionar Armazenamento", -"None set" => "Nenhum definido", +"No user or group" => "Nenhum usuário ou grupo", "All Users" => "Todos os Usuários", "Groups" => "Grupos", "Users" => "Usuários", diff --git a/apps/files_external/l10n/pt_PT.php b/apps/files_external/l10n/pt_PT.php index eb4d8feb41a80349a421870bc637a29ef53d1717..d0b70006ea1a0d1b85c5ea891432e9b1daccd13b 100644 --- a/apps/files_external/l10n/pt_PT.php +++ b/apps/files_external/l10n/pt_PT.php @@ -6,17 +6,12 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Por favor forneça uma \"app key\" e \"secret\" do Dropbox válidas.", "Error configuring Google Drive storage" => "Erro ao configurar o armazenamento do Google Drive", "Saved" => "Guardado", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Atenção: O cliente \"smbclient\" não está instalado. Não é possível montar as partilhas CIFS/SMB . Peça ao seu administrador para instalar.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Aviso: O suporte FTP no PHP não está activate ou instalado. Não é possível montar as partilhas FTP. Peça ao seu administrador para instalar.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Atenção:
O suporte PHP para o Curl não está activado ou instalado. A montagem do ownCloud/WebDav ou GoolgeDriver não é possível. Por favor contacte o administrador para o instalar.", "External Storage" => "Armazenamento Externo", "Folder name" => "Nome da pasta", "External storage" => "Armazenamento Externo", "Configuration" => "Configuração", "Options" => "Opções", -"Applicable" => "Aplicável", "Add storage" => "Adicionar armazenamento", -"None set" => "Não definido", "All Users" => "Todos os utilizadores", "Groups" => "Grupos", "Users" => "Utilizadores", diff --git a/apps/files_external/l10n/ro.php b/apps/files_external/l10n/ro.php index a90b0299e1766cca987ce51bc3db781077a41492..3fc56c67d333fffbbd9dc8af7c649baa22119dc5 100644 --- a/apps/files_external/l10n/ro.php +++ b/apps/files_external/l10n/ro.php @@ -6,17 +6,12 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Prezintă te rog o cheie de Dropbox validă și parola", "Error configuring Google Drive storage" => "Eroare la configurarea mediului de stocare Google Drive", "Saved" => "Salvat", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Atenție: \"smbclient\" nu este instalat. Montarea mediilor CIFS/SMB partajate nu este posibilă. Solicită administratorului sistemului tău să îl instaleaze.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Atenție: suportul pentru FTP în PHP nu este activat sau instalat. Montarea mediilor FPT partajate nu este posibilă. Solicită administratorului sistemului tău să îl instaleze.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Atentie: Suportul Curl nu este pornit / instalat in configuratia PHP! Montarea ownCloud / WebDAV / GoogleDrive nu este posibila! Intrebati administratorul sistemului despre aceasta problema!", "External Storage" => "Stocare externă", "Folder name" => "Denumire director", "External storage" => "Stocare externă", "Configuration" => "Configurație", "Options" => "Opțiuni", -"Applicable" => "Aplicabil", "Add storage" => "Adauga stocare", -"None set" => "Niciunul", "All Users" => "Toți utilizatorii", "Groups" => "Grupuri", "Users" => "Utilizatori", diff --git a/apps/files_external/l10n/ru.php b/apps/files_external/l10n/ru.php index 66d6f9fa6b8d44dff6bcd23be701564025b56b39..f282f3969e5654e26e84c97c030944d5affe0eac 100644 --- a/apps/files_external/l10n/ru.php +++ b/apps/files_external/l10n/ru.php @@ -5,22 +5,19 @@ $TRANSLATIONS = array( "Grant access" => "Предоставление доступа", "Please provide a valid Dropbox app key and secret." => "Пожалуйста, предоставьте действующий ключ Dropbox и пароль.", "Error configuring Google Drive storage" => "Ошибка при настройке хранилища Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Внимание: \"smbclient\" не установлен. Подключение по CIFS/SMB невозможно. Пожалуйста, обратитесь к системному администратору, чтобы установить его.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Внимание: Поддержка FTP не включена в PHP. Подключение по FTP невозможно. Пожалуйста, обратитесь к системному администратору, чтобы включить.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Внимание: Поддержка Curl в PHP не включена или не установлена. Подключение ownCloud / WebDAV или GoogleDrive невозможно. Попросите вашего системного администратора установить его.", +"Saved" => "Сохранено", "External Storage" => "Внешний носитель", "Folder name" => "Имя папки", "External storage" => "Внешний носитель данных", "Configuration" => "Конфигурация", "Options" => "Опции", -"Applicable" => "Применимый", "Add storage" => "Добавить носитель данных", -"None set" => "Не установлено", "All Users" => "Все пользователи", "Groups" => "Группы", "Users" => "Пользователи", "Delete" => "Удалить", "Enable User External Storage" => "Включить пользовательские внешние носители", +"Allow users to mount the following external storage" => "Разрешить пользователям монтировать следующую внешнюю систему хранения данных", "SSL root certificates" => "Корневые сертификаты SSL", "Import Root Certificate" => "Импортировать корневые сертификаты" ); diff --git a/apps/files_external/l10n/si_LK.php b/apps/files_external/l10n/si_LK.php index ac41f596340c95e52da71c209e59bbed2ad72983..a9f39a3bbc959d7b1dbe48d3cff9a7f50fdbe374 100644 --- a/apps/files_external/l10n/si_LK.php +++ b/apps/files_external/l10n/si_LK.php @@ -9,8 +9,6 @@ $TRANSLATIONS = array( "Folder name" => "ෆොල්ඩරයේ නම", "Configuration" => "වින්‍යාසය", "Options" => "විකල්පයන්", -"Applicable" => "අදාළ", -"None set" => "කිසිවක් නැත", "All Users" => "සියළු පරිශීලකයන්", "Groups" => "කණ්ඩායම්", "Users" => "පරිශීලකයන්", diff --git a/apps/files_external/l10n/sk_SK.php b/apps/files_external/l10n/sk_SK.php index aa28898257640868f6f86920e35f9b85ec76321f..de32fb5ffb16b08c11b6e4f9351a60ce69ae84d9 100644 --- a/apps/files_external/l10n/sk_SK.php +++ b/apps/files_external/l10n/sk_SK.php @@ -5,17 +5,13 @@ $TRANSLATIONS = array( "Grant access" => "Povoliť prístup", "Please provide a valid Dropbox app key and secret." => "Zadajte platný kľúč aplikácie a heslo Dropbox", "Error configuring Google Drive storage" => "Chyba pri konfigurácii úložiska Google drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Upozornenie: \"smbclient\" nie je nainštalovaný. Nie je možné pripojenie oddielov CIFS/SMB. Požiadajte administrátora systému, nech ho nainštaluje.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Upozornenie: Podpora FTP v PHP nie je povolená alebo nainštalovaná. Nie je možné pripojenie oddielov FTP. Požiadajte administrátora systému, nech ho nainštaluje.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Varovanie: nie je nainštalovaná, alebo povolená, podpora Curl v PHP. Nie je možné pripojenie oddielov ownCloud, WebDAV, či GoogleDrive. Prosím požiadajte svojho administrátora systému, nech ju nainštaluje.", +"Saved" => "Uložené", "External Storage" => "Externé úložisko", "Folder name" => "Názov priečinka", "External storage" => "Externé úložisko", "Configuration" => "Nastavenia", "Options" => "Možnosti", -"Applicable" => "Aplikovateľné", "Add storage" => "Pridať úložisko", -"None set" => "Žiadne nastavené", "All Users" => "Všetci používatelia", "Groups" => "Skupiny", "Users" => "Používatelia", diff --git a/apps/files_external/l10n/sl.php b/apps/files_external/l10n/sl.php index 05e626fcf831967a62aee350663f8b964ca74e40..bb34494a5d7e42effbdf15f1c3f33a18a782bba9 100644 --- a/apps/files_external/l10n/sl.php +++ b/apps/files_external/l10n/sl.php @@ -6,17 +6,14 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Vpisati je treba veljaven ključ programa in kodo za Dropbox", "Error configuring Google Drive storage" => "Napaka nastavljanja shrambe Google Drive", "Saved" => "Shranjeno", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Opozorilo: paket \"smbclient\" ni nameščen. Priklapljanje pogonov CIFS/SMB ne bo mogoče.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Opozorilo: podpora FTP v PHP ni omogočena ali pa ni nameščena. Priklapljanje pogonov FTP zato ne bo mogoče.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Opozorilo: podpora za Curl v PHP ni omogočena ali pa ni nameščena. Priklapljanje točke ownCloud / WebDAV ali GoogleDrive zato ne bo mogoče. Zahtevane pakete je treba pred uporabo namestiti.", "External Storage" => "Zunanja podatkovna shramba", "Folder name" => "Ime mape", "External storage" => "Zunanja shramba", "Configuration" => "Nastavitve", "Options" => "Možnosti", -"Applicable" => "Se uporablja", +"Available for" => "Na voljo za", "Add storage" => "Dodaj shrambo", -"None set" => "Ni nastavljeno", +"No user or group" => "Ni uporabnika ali skupine", "All Users" => "Vsi uporabniki", "Groups" => "Skupine", "Users" => "Uporabniki", diff --git a/apps/files_external/l10n/sv.php b/apps/files_external/l10n/sv.php index 183df674b9d5ac8b9e3fa0e1c3e3066b34b7c0bb..2992460d283d3467b4571936f57009b0df5e93b6 100644 --- a/apps/files_external/l10n/sv.php +++ b/apps/files_external/l10n/sv.php @@ -5,22 +5,26 @@ $TRANSLATIONS = array( "Grant access" => "Bevilja åtkomst", "Please provide a valid Dropbox app key and secret." => "Ange en giltig Dropbox nyckel och hemlighet.", "Error configuring Google Drive storage" => "Fel vid konfigurering av Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Varning: \"smb-klienten\" är inte installerad. Montering av CIFS/SMB delningar är inte möjligt. Kontakta din systemadministratör för att få den installerad.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Varning: Stöd för FTP i PHP är inte aktiverat eller installerat. Montering av FTP-delningar är inte möjligt. Kontakta din systemadministratör för att få det installerat.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Varning: Curl-stöd i PHP är inte aktiverat eller installerat. Montering av ownCloud / WebDAV eller GoogleDrive är inte möjligt. Vänligen be din administratör att installera det.", +"Saved" => "Sparad", +"Note: " => " OBS: ", +" and " => "och", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => " OBS: cURL stöd i PHP inte är aktiverat eller installeras. Montering av %s är inte möjlig. Be din systemadministratör för att installera det.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => " OBS: Den FTP-stöd i PHP inte är aktiverat eller installeras. Montering av %s är inte möjlig. Be din systemadministratör för att installera det.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => " OBS: \"%s\" är inte installerat. Montering av %s är inte möjlig. Be din systemadministratör för att installera det.", "External Storage" => "Extern lagring", "Folder name" => "Mappnamn", "External storage" => "Extern lagring", "Configuration" => "Konfiguration", "Options" => "Alternativ", -"Applicable" => "Tillämplig", +"Available for" => "Tillgänglig för", "Add storage" => "Lägg till lagring", -"None set" => "Ingen angiven", +"No user or group" => "Ingen användare eller grupp", "All Users" => "Alla användare", "Groups" => "Grupper", "Users" => "Användare", "Delete" => "Radera", "Enable User External Storage" => "Aktivera extern lagring för användare", +"Allow users to mount the following external storage" => "Tillåt användare att montera följande extern lagring", "SSL root certificates" => "SSL rotcertifikat", "Import Root Certificate" => "Importera rotcertifikat" ); diff --git a/apps/files_external/l10n/ta_LK.php b/apps/files_external/l10n/ta_LK.php index 94ddaf9c5e139af92ef36e1aa133137afb2e88ef..fe5d2a8bc87df467d046e9604e0d7b840fe368f3 100644 --- a/apps/files_external/l10n/ta_LK.php +++ b/apps/files_external/l10n/ta_LK.php @@ -9,8 +9,6 @@ $TRANSLATIONS = array( "Folder name" => "கோப்புறை பெயர்", "Configuration" => "தகவமைப்பு", "Options" => "தெரிவுகள்", -"Applicable" => "பயன்படத்தக்க", -"None set" => "தொகுப்பில்லா", "All Users" => "பயனாளர்கள் எல்லாம்", "Groups" => "குழுக்கள்", "Users" => "பயனாளர்", diff --git a/apps/files_external/l10n/th_TH.php b/apps/files_external/l10n/th_TH.php index a1a56a4d2e49f56d2d2a39d1d677fe1211133ace..e3653eb41f7acdd3c47f24e0de136f43133e16c8 100644 --- a/apps/files_external/l10n/th_TH.php +++ b/apps/files_external/l10n/th_TH.php @@ -5,14 +5,10 @@ $TRANSLATIONS = array( "Grant access" => "อนุญาตให้เข้าถึงได้", "Please provide a valid Dropbox app key and secret." => "กรุณากรอกรหัส app key ของ Dropbox และรหัสลับ", "Error configuring Google Drive storage" => "เกิดข้อผิดพลาดในการกำหนดค่าการจัดเก็บข้อมูลในพื้นที่ของ Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "คำเตือน: \"smbclient\" ยังไม่ได้ถูกติดตั้ง. การชี้ CIFS/SMB เพื่อแชร์ข้อมูลไม่สามารถกระทำได้ กรุณาสอบถามข้อมูลเพิ่มเติมจากผู้ดูแลระบบเพื่อติดตั้ง.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "คำเตือน: การสนับสนุนการใช้งาน FTP ในภาษา PHP ยังไม่ได้ถูกเปิดใช้งานหรือถูกติดตั้ง. การชี้ FTP เพื่อแชร์ข้อมูลไม่สามารถดำเนินการได้ กรุณาสอบถามข้อมูลเพิ่มเติมจากผู้ดูแลระบบเพื่อติดตั้ง", "External Storage" => "พื้นทีจัดเก็บข้อมูลจากภายนอก", "Folder name" => "ชื่อโฟลเดอร์", "Configuration" => "การกำหนดค่า", "Options" => "ตัวเลือก", -"Applicable" => "สามารถใช้งานได้", -"None set" => "ยังไม่มีการกำหนด", "All Users" => "ผู้ใช้งานทั้งหมด", "Groups" => "กลุ่ม", "Users" => "ผู้ใช้งาน", diff --git a/apps/files_external/l10n/tr.php b/apps/files_external/l10n/tr.php index a835d6f174acd98ef8f98e2c9c2905bee81c0663..3646a47605d5ea0c371e30c8ebdc1bcd45d15c13 100644 --- a/apps/files_external/l10n/tr.php +++ b/apps/files_external/l10n/tr.php @@ -6,17 +6,19 @@ $TRANSLATIONS = array( "Please provide a valid Dropbox app key and secret." => "Lütfen Dropbox app key ve secret temin ediniz", "Error configuring Google Drive storage" => "Google Drive depo yapılandırma hatası", "Saved" => "Kaydedildi", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Uyarı: \"smbclient\" kurulu değil. CIFS/SMB paylaşımlarını bağlama işlemi mümkün olmadı. Lütfen kurulumu için sistem yöneticinize danışın.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Uyarı: PHP içerisinde FTP desteği etkin veya yüklü değil. FTP paylaşımlarını bağlama işlemi mümkün olmadı. Lütfen kurulumu için sistem yöneticinize danışın.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Uyarı: PHP içerisinde Curl desteği etkin veya yüklü değil. OwnCloud / WebDAV veya GoogleDrive bağlama işlemi mümkün olmadı. Lütfen kurulumu için sistem yöneticinizde danışın.", +"Note: " => "Not: ", +" and " => "ve", +"Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Not: 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.", +"Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Not: 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.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Not: \"%s\" kurulu değil. %s bağlaması mümkün olmayacak. Lütfen kurulumu için sistem yöneticilerinizle iletişime geçin.", "External Storage" => "Harici Depolama", -"Folder name" => "Dizin ismi", +"Folder name" => "Klasör ismi", "External storage" => "Harici depolama", "Configuration" => "Yapılandırma", "Options" => "Seçenekler", -"Applicable" => "Uygulanabilir", +"Available for" => "Kullanabilenler", "Add storage" => "Depo ekle", -"None set" => "Hiçbiri", +"No user or group" => "Kullanıcı veya grup yok", "All Users" => "Tüm Kullanıcılar", "Groups" => "Gruplar", "Users" => "Kullanıcılar", diff --git a/apps/files_external/l10n/uk.php b/apps/files_external/l10n/uk.php index a7c028aa9356d1cadf50b16d652d70131d2dd5f7..533eba07eb1ccc449406af431ef92d6b81ba97c1 100644 --- a/apps/files_external/l10n/uk.php +++ b/apps/files_external/l10n/uk.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Дозволити доступ", "Please provide a valid Dropbox app key and secret." => "Будь ласка, надайте дійсний ключ та пароль Dropbox.", "Error configuring Google Drive storage" => "Помилка при налаштуванні сховища Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Попередження: Клієнт \"smbclient\" не встановлено. Під'єднанатися до CIFS/SMB тек неможливо. Попрохайте системного адміністратора встановити його.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Попередження: Підтримка FTP в PHP не увімкнута чи не встановлена. Під'єднанатися до FTP тек неможливо. Попрохайте системного адміністратора встановити її.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Попередження: Підтримка CURL в PHP не увімкнута чи не встановлена. Під'єднанатися OwnCloud / WebDav або Google Drive неможливе. Попрохайте системного адміністратора встановити її.", "External Storage" => "Зовнішні сховища", "Folder name" => "Ім'я теки", "External storage" => "Зовнішнє сховище", "Configuration" => "Налаштування", "Options" => "Опції", -"Applicable" => "Придатний", "Add storage" => "Додати сховище", -"None set" => "Не встановлено", "All Users" => "Усі користувачі", "Groups" => "Групи", "Users" => "Користувачі", diff --git a/apps/files_external/l10n/vi.php b/apps/files_external/l10n/vi.php index 5fd00dc2bf54c2a7d28156e9bc8a4c676519452e..787fc82832e7fa33c3a1e065914792b7b94cdb36 100644 --- a/apps/files_external/l10n/vi.php +++ b/apps/files_external/l10n/vi.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "Cấp quyền truy cập", "Please provide a valid Dropbox app key and secret." => "Xin vui lòng cung cấp một ứng dụng Dropbox hợp lệ và mã bí mật.", "Error configuring Google Drive storage" => "Lỗi cấu hình lưu trữ Google Drive", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "Cảnh báo: \"smbclient\" chưa được cài đặt. Mount CIFS/SMB shares là không thể thực hiện được. Hãy hỏi người quản trị hệ thống để cài đặt nó.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "Cảnh báo: FTP trong PHP chưa được cài đặt hoặc chưa được mở. Mount FTP shares là không thể. Xin hãy yêu cầu quản trị hệ thống của bạn cài đặt nó.", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "Cảnh báo: Tính năng Curl trong PHP chưa được kích hoạt hoặc cài đặt. Việc gắn kết ownCloud / WebDAV hay GoogleDrive không thực hiện được. Vui lòng liên hệ người quản trị để cài đặt nó.", "External Storage" => "Lưu trữ ngoài", "Folder name" => "Tên thư mục", "External storage" => "Lưu trữ ngoài", "Configuration" => "Cấu hình", "Options" => "Tùy chọn", -"Applicable" => "Áp dụng", "Add storage" => "Thêm bộ nhớ", -"None set" => "không", "All Users" => "Tất cả người dùng", "Groups" => "Nhóm", "Users" => "Người dùng", diff --git a/apps/files_external/l10n/zh_CN.php b/apps/files_external/l10n/zh_CN.php index bb85d0e4f495e0bddd748869a8c20f2cffc9c383..40d5158bf5c9a0436cb6106d4f468fab08ebfaa5 100644 --- a/apps/files_external/l10n/zh_CN.php +++ b/apps/files_external/l10n/zh_CN.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "授权", "Please provide a valid Dropbox app key and secret." => "请提供有效的Dropbox应用key和secret", "Error configuring Google Drive storage" => "配置Google Drive存储时出错", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "警告:“smbclient” 尚未安装。CIFS/SMB 分享挂载无法实现。请咨询系统管理员进行安装。", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "警告:PHP中尚未启用或安装FTP。FTP 分享挂载无法实现。请咨询系统管理员进行安装。", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "警告: PHP中未启用或未安装Curl支持。ownCloud / WebDAV 或 GoogleDrive 不能挂载。请请求您的系统管理员安装该它。", "External Storage" => "外部存储", "Folder name" => "目录名称", "External storage" => "外部存储", "Configuration" => "配置", "Options" => "选项", -"Applicable" => "适用的", "Add storage" => "添加存储", -"None set" => "未设置", "All Users" => "所有用户", "Groups" => "组", "Users" => "用户", diff --git a/apps/files_external/l10n/zh_TW.php b/apps/files_external/l10n/zh_TW.php index 7c256cd2ab713f31b6c9bb6beb4476f4385ceb88..ac480e405fb6c3264d97f2b48a66d78a29b65b2e 100644 --- a/apps/files_external/l10n/zh_TW.php +++ b/apps/files_external/l10n/zh_TW.php @@ -5,17 +5,12 @@ $TRANSLATIONS = array( "Grant access" => "允許存取", "Please provide a valid Dropbox app key and secret." => "請提供有效的 Dropbox app key 和 app secret 。", "Error configuring Google Drive storage" => "設定 Google Drive 儲存時發生錯誤", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "警告:未安裝 \"smbclient\" ,因此無法掛載 CIFS/SMB 分享,請洽您的系統管理員將其安裝。", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "警告:PHP 並未啓用 FTP 的支援,因此無法掛載 FTP 分享,請洽您的系統管理員將其安裝並啓用。", -"Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it." => "警告:PHP 並未啓用 Curl 的支援,因此無法掛載 ownCloud/WebDAV 或 Google Drive 分享,請洽您的系統管理員將其安裝並啓用。", "External Storage" => "外部儲存", "Folder name" => "資料夾名稱", "External storage" => "外部儲存", "Configuration" => "設定", "Options" => "選項", -"Applicable" => "可用的", "Add storage" => "增加儲存區", -"None set" => "尚未設定", "All Users" => "所有使用者", "Groups" => "群組", "Users" => "使用者", diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 06ccd5d16fa0d2efc53adfa176ac9f0f04ef19af..2093fb7e58cf7aadf249db84cc9614fb904d4cb8 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -548,4 +548,16 @@ class AmazonS3 extends \OC\Files\Storage\Common { return false; } } + + /** + * check if curl is installed + */ + public static function checkDependencies() { + if (function_exists('curl_init')) { + return true; + } else { + return array('curl'); + } + } + } diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index c5b091336e197ad803c602d3c87fa305ff292bd3..71f6ae7887830e4a09ea5397eddcc854517a4605 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -5,6 +5,7 @@ * @author Michael Gapczynski * @copyright 2012 Michael Gapczynski mtgap@owncloud.com * @copyright 2014 Vincent Petry +* @copyright 2014 Robin McCorkell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -38,6 +39,34 @@ class OC_Mount_Config { // whether to skip backend test (for unit tests, as this static class is not mockable) public static $skipTest = false; + private static $backends = array(); + + /** + * @param string $class + * @param array $definition + * @return bool + */ + public static function registerBackend($class, $definition) { + if (!isset($definition['backend'])) { + return false; + } + + OC_Mount_Config::$backends[$class] = $definition; + return true; + } + + /** + * Setup backends + * + * @return array of previously registered backends + */ + public static function setUp($backends = array()) { + $backup = self::$backends; + self::$backends = $backends; + + return $backup; + } + /** * Get details on each of the external storage backends, used for the mount config UI * If a custom UI is needed, add the key 'custom' and a javascript file with that name will be loaded @@ -45,125 +74,32 @@ class OC_Mount_Config { * If the configuration parameter is a boolean, add a '!' to the beginning of the value * If the configuration parameter is optional, add a '&' to the beginning of the value * If the configuration parameter is hidden, add a '#' to the beginning of the value - * @return string + * @return array */ public static function getBackends() { - - // FIXME: do not rely on php key order for the options order in the UI - $backends['\OC\Files\Storage\Local']=array( - 'backend' => 'Local', - 'configuration' => array( - 'datadir' => 'Location')); - - $backends['\OC\Files\Storage\AmazonS3']=array( - 'backend' => 'Amazon S3 and compliant', - 'configuration' => array( - 'key' => 'Access Key', - 'secret' => '*Secret Key', - 'bucket' => 'Bucket', - 'hostname' => '&Hostname (optional)', - 'port' => '&Port (optional)', - 'region' => '&Region (optional)', - 'use_ssl' => '!Enable SSL', - 'use_path_style' => '!Enable Path Style')); - - $backends['\OC\Files\Storage\Dropbox']=array( - 'backend' => 'Dropbox', - 'configuration' => array( - 'configured' => '#configured', - 'app_key' => 'App key', - 'app_secret' => '*App secret', - 'token' => '#token', - 'token_secret' => '#token_secret'), - 'custom' => 'dropbox'); - - if(OC_Mount_Config::checkphpftp()) $backends['\OC\Files\Storage\FTP']=array( - 'backend' => 'FTP', - 'configuration' => array( - 'host' => 'Hostname', - 'user' => 'Username', - 'password' => '*Password', - 'root' => '&Root', - 'secure' => '!Secure ftps://')); - - if(OC_Mount_Config::checkcurl()) $backends['\OC\Files\Storage\Google']=array( - 'backend' => 'Google Drive', - 'configuration' => array( - 'configured' => '#configured', - 'client_id' => 'Client ID', - 'client_secret' => '*Client secret', - 'token' => '#token'), - 'custom' => 'google'); - - if(OC_Mount_Config::checkcurl()) { - $backends['\OC\Files\Storage\Swift'] = array( - 'backend' => 'OpenStack Object Storage', - 'configuration' => array( - 'user' => 'Username (required)', - 'bucket' => 'Bucket (required)', - 'region' => '&Region (optional for OpenStack Object Storage)', - 'key' => '*API Key (required for Rackspace Cloud Files)', - 'tenant' => '&Tenantname (required for OpenStack Object Storage)', - 'password' => '*Password (required for OpenStack Object Storage)', - 'service_name' => '&Service Name (required for OpenStack Object Storage)', - 'url' => '&URL of identity endpoint (required for OpenStack Object Storage)', - 'timeout' => '&Timeout of HTTP requests in seconds (optional)', - ) - ); - } - - if (!OC_Util::runningOnWindows()) { - if (OC_Mount_Config::checksmbclient()) { - $backends['\OC\Files\Storage\SMB'] = array( - 'backend' => 'SMB / CIFS', - 'configuration' => array( - 'host' => 'URL', - 'user' => 'Username', - 'password' => '*Password', - 'share' => 'Share', - 'root' => '&Root')); + $sortFunc = function($a, $b) { + return strcasecmp($a['backend'], $b['backend']); + }; + + $backEnds = array(); + + foreach (OC_Mount_Config::$backends as $class => $backend) { + if (isset($backend['has_dependencies']) and $backend['has_dependencies'] === true) { + if (!method_exists($class, 'checkDependencies')) { + \OCP\Util::writeLog('files_external', + "Backend class $class has dependencies but doesn't provide method checkDependencies()", + \OCP\Util::DEBUG); + continue; + } elseif ($class::checkDependencies() !== true) { + continue; + } } + $backEnds[$class] = $backend; } - if(OC_Mount_Config::checkcurl()){ - $backends['\OC\Files\Storage\DAV']=array( - 'backend' => 'WebDAV', - 'configuration' => array( - 'host' => 'URL', - 'user' => 'Username', - 'password' => '*Password', - 'root' => '&Root', - 'secure' => '!Secure https://')); - $backends['\OC\Files\Storage\OwnCloud']=array( - 'backend' => 'ownCloud', - 'configuration' => array( - 'host' => 'URL', - 'user' => 'Username', - 'password' => '*Password', - 'root' => '&Remote subfolder', - 'secure' => '!Secure https://')); - } - - $backends['\OC\Files\Storage\SFTP']=array( - 'backend' => 'SFTP', - 'configuration' => array( - 'host' => 'URL', - 'user' => 'Username', - 'password' => '*Password', - 'root' => '&Root')); - - $backends['\OC\Files\Storage\iRODS']=array( - 'backend' => 'iRODS', - 'configuration' => array( - 'host' => 'Host', - 'port' => 'Port', - 'use_logon_credentials' => '!Use ownCloud login', - 'user' => 'Username', - 'password' => '*Password', - 'auth_mode' => 'Authentication Mode', - 'zone' => 'Zone')); - - return($backends); + uasort($backEnds, $sortFunc); + + return $backEnds; } /** @@ -185,7 +121,7 @@ class OC_Mount_Config { * @return array of mount point string as key, mountpoint config as value */ public static function getAbsoluteMountPoints($user) { - $mountPoints = array(); + $mountPoints = array(); $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data"); $mount_file = \OC_Config::getValue("mount_file", $datadir . "/mount.json"); @@ -270,19 +206,25 @@ class OC_Mount_Config { */ public static function getPersonalBackends() { - $backends = self::getBackends(); + // Check whether the user has permissions to add personal storage backends + // return an empty array if this is not the case + if(OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') !== 'yes') { + return array(); + } + + $backEnds = self::getBackends(); // Remove local storage and other disabled storages - unset($backends['\OC\Files\Storage\Local']); + unset($backEnds['\OC\Files\Storage\Local']); - $allowed_backends = explode(',', OCP\Config::getAppValue('files_external', 'user_mounting_backends', '')); - foreach ($backends as $backend => $null) { - if (!in_array($backend, $allowed_backends)) { - unset($backends[$backend]); + $allowedBackEnds = explode(',', OCP\Config::getAppValue('files_external', 'user_mounting_backends', '')); + foreach ($backEnds as $backend => $null) { + if (!in_array($backend, $allowedBackEnds)) { + unset($backEnds[$backend]); } } - return $backends; + return $backEnds; } /** @@ -304,18 +246,23 @@ class OC_Mount_Config { $mount['options'] = self::decryptPasswords($mount['options']); // Remove '/$user/files/' from mount point $mountPoint = substr($mountPoint, 13); - // Merge the mount point into the current mount points - if (isset($system[$mountPoint]) && $system[$mountPoint]['configuration'] == $mount['options']) { - $system[$mountPoint]['applicable']['groups'] - = array_merge($system[$mountPoint]['applicable']['groups'], array($group)); + + $config = array( + 'class' => $mount['class'], + 'mountpoint' => $mountPoint, + 'backend' => $backends[$mount['class']]['backend'], + 'options' => $mount['options'], + 'applicable' => array('groups' => array($group), 'users' => array()), + 'status' => self::getBackendStatus($mount['class'], $mount['options'], false) + ); + $hash = self::makeConfigHash($config); + // If an existing config exists (with same class, mountpoint and options) + if (isset($system[$hash])) { + // add the groups into that config + $system[$hash]['applicable']['groups'] + = array_merge($system[$hash]['applicable']['groups'], array($group)); } else { - $system[$mountPoint] = array( - 'class' => $mount['class'], - 'backend' => $backends[$mount['class']]['backend'], - 'configuration' => $mount['options'], - 'applicable' => array('groups' => array($group), 'users' => array()), - 'status' => self::getBackendStatus($mount['class'], $mount['options']) - ); + $system[$hash] = $config; } } } @@ -330,23 +277,27 @@ class OC_Mount_Config { $mount['options'] = self::decryptPasswords($mount['options']); // Remove '/$user/files/' from mount point $mountPoint = substr($mountPoint, 13); - // Merge the mount point into the current mount points - if (isset($system[$mountPoint]) && $system[$mountPoint]['configuration'] == $mount['options']) { - $system[$mountPoint]['applicable']['users'] - = array_merge($system[$mountPoint]['applicable']['users'], array($user)); + $config = array( + 'class' => $mount['class'], + 'mountpoint' => $mountPoint, + 'backend' => $backends[$mount['class']]['backend'], + 'options' => $mount['options'], + 'applicable' => array('groups' => array(), 'users' => array($user)), + 'status' => self::getBackendStatus($mount['class'], $mount['options'], false) + ); + $hash = self::makeConfigHash($config); + // If an existing config exists (with same class, mountpoint and options) + if (isset($system[$hash])) { + // add the users into that config + $system[$hash]['applicable']['users'] + = array_merge($system[$hash]['applicable']['users'], array($user)); } else { - $system[$mountPoint] = array( - 'class' => $mount['class'], - 'backend' => $backends[$mount['class']]['backend'], - 'configuration' => $mount['options'], - 'applicable' => array('groups' => array(), 'users' => array($user)), - 'status' => self::getBackendStatus($mount['class'], $mount['options']) - ); + $system[$hash] = $config; } } } } - return $system; + return array_values($system); } /** @@ -356,7 +307,7 @@ class OC_Mount_Config { */ public static function getPersonalMountPoints() { $mountPoints = self::readData(true); - $backends = self::getBackends(); + $backEnds = self::getBackends(); $uid = OCP\User::getUser(); $personal = array(); if (isset($mountPoints[self::MOUNT_TYPE_USER][$uid])) { @@ -366,12 +317,13 @@ class OC_Mount_Config { $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } $mount['options'] = self::decryptPasswords($mount['options']); - // Remove '/uid/files/' from mount point - $personal[substr($mountPoint, strlen($uid) + 8)] = array( + $personal[] = array( 'class' => $mount['class'], - 'backend' => $backends[$mount['class']]['backend'], - 'configuration' => $mount['options'], - 'status' => self::getBackendStatus($mount['class'], $mount['options']) + // Remove '/uid/files/' from mount point + 'mountpoint' => substr($mountPoint, strlen($uid) + 8), + 'backend' => $backEnds[$mount['class']]['backend'], + 'options' => $mount['options'], + 'status' => self::getBackendStatus($mount['class'], $mount['options'], true) ); } } @@ -384,7 +336,7 @@ class OC_Mount_Config { * @param array $options backend configuration options * @return bool true if the connection succeeded, false otherwise */ - private static function getBackendStatus($class, $options) { + private static function getBackendStatus($class, $options, $isPersonal) { if (self::$skipTest) { return true; } @@ -394,7 +346,7 @@ class OC_Mount_Config { if (class_exists($class)) { try { $storage = new $class($options); - return $storage->test(); + return $storage->test($isPersonal); } catch (Exception $exception) { \OCP\Util::logException('files_external', $exception); return false; @@ -461,7 +413,7 @@ class OC_Mount_Config { $mountPoints[$mountType] = $mount; } self::writeData($isPersonal, $mountPoints); - return self::getBackendStatus($class, $classOptions); + return self::getBackendStatus($class, $classOptions, $isPersonal); } /** @@ -596,54 +548,91 @@ class OC_Mount_Config { } /** - * check if smbclient is installed + * check dependencies */ - public static function checksmbclient() { - if(function_exists('shell_exec')) { - $output=shell_exec('command -v smbclient 2> /dev/null'); - return !empty($output); - }else{ - return false; + public static function checkDependencies() { + $dependencies = array(); + foreach (OC_Mount_Config::$backends as $class => $backend) { + if (isset($backend['has_dependencies']) and $backend['has_dependencies'] === true) { + $result = $class::checkDependencies(); + if ($result !== true) { + if (!is_array($result)) { + $result = array($result); + } + foreach ($result as $key => $value) { + if (is_numeric($key)) { + OC_Mount_Config::addDependency($dependencies, $value, $backend['backend']); + } else { + OC_Mount_Config::addDependency($dependencies, $key, $backend['backend'], $value); + } + } + } + } + } + + if (count($dependencies) > 0) { + return OC_Mount_Config::generateDependencyMessage($dependencies); } + return ''; } - /** - * check if php-ftp is installed - */ - public static function checkphpftp() { - if(function_exists('ftp_login')) { - return true; - }else{ - return false; + private static function addDependency(&$dependencies, $module, $backend, $message=null) { + if (!isset($dependencies[$module])) { + $dependencies[$module] = array(); + } + + if ($message === null) { + $dependencies[$module][] = $backend; + } else { + $dependencies[$module][] = array('backend' => $backend, 'message' => $message); } } - /** - * check if curl is installed - */ - public static function checkcurl() { - return function_exists('curl_init'); + private static function generateDependencyMessage($dependencies) { + $l = new \OC_L10N('files_external'); + $dependencyMessage = ''; + foreach ($dependencies as $module => $backends) { + $dependencyGroup = array(); + foreach ($backends as $backend) { + if (is_array($backend)) { + $dependencyMessage .= '
' . $l->t('Note: ') . $backend['message']; + } else { + $dependencyGroup[] = $backend; + } + } + + if (count($dependencyGroup) > 0) { + $backends = ''; + for ($i = 0; $i < count($dependencyGroup); $i++) { + if ($i > 0 && $i === count($dependencyGroup) - 1) { + $backends .= $l->t(' and '); + } elseif ($i > 0) { + $backends .= ', '; + } + $backends .= '' . $dependencyGroup[$i] . ''; + } + $dependencyMessage .= '
' . OC_Mount_Config::getSingleDependencyMessage($l, $module, $backends); + } + } + return $dependencyMessage; } /** - * check dependencies + * Returns a dependency missing message + * @param $l OC_L10N + * @param $module string + * @param $backend string + * @return string */ - public static function checkDependencies() { - $l= new OC_L10N('files_external'); - $txt=''; - if (!OC_Util::runningOnWindows()) { - if(!OC_Mount_Config::checksmbclient()) { - $txt.=$l->t('Warning: "smbclient" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it.').'
'; - } - } - if(!OC_Mount_Config::checkphpftp()) { - $txt.=$l->t('Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it.').'
'; + private static function getSingleDependencyMessage($l, $module, $backend) { + switch (strtolower($module)) { + case 'curl': + return $l->t('Note: The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', $backend); + case 'ftp': + return $l->t('Note: The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', $backend); + default: + return $l->t('Note: "%s" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it.', array($module, $backend)); } - if(!OC_Mount_Config::checkcurl()) { - $txt.=$l->t('Warning: The Curl support in PHP is not enabled or installed. Mounting of ownCloud / WebDAV or GoogleDrive is not possible. Please ask your system administrator to install it.').'
'; - } - - return $txt; } /** @@ -712,4 +701,20 @@ class OC_Mount_Config { $cipher->setKey(\OCP\Config::getSystemValue('passwordsalt')); return $cipher; } + + /** + * Computes a hash based on the given configuration. + * This is mostly used to find out whether configurations + * are the same. + */ + private static function makeConfigHash($config) { + $data = json_encode( + array( + 'c' => $config['class'], + 'm' => $config['mountpoint'], + 'o' => $config['options'] + ) + ); + return hash('md5', $data); + } } diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 0214e18020c3923bb98d052650aaf221fe80ac91..38de3360f2b40c348427e5c15a04774ebd67a33f 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -311,4 +311,15 @@ class Dropbox extends \OC\Files\Storage\Common { return true; } + /** + * check if curl is installed + */ + public static function checkDependencies() { + if (function_exists('curl_init')) { + return true; + } else { + return array('curl'); + } + } + } diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php index 00bf7a189cebabba35e76880e8aec7b69edf8b6c..b3f8b1444ae5d599de0ba504f8d2689adde0ca81 100644 --- a/apps/files_external/lib/ftp.php +++ b/apps/files_external/lib/ftp.php @@ -119,4 +119,16 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ unlink($tmpFile); } } + + /** + * check if php-ftp is installed + */ + public static function checkDependencies() { + if (function_exists('ftp_login')) { + return(true); + } else { + return array('ftp'); + } + } + } diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 35457f6852841dec9e55621c245d0526e4b6f49d..56c0d451651b15c0f59d6e80cf9303d5c8b15bcd 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -586,4 +586,15 @@ class Google extends \OC\Files\Storage\Common { return false; } + /** + * check if curl is installed + */ + public static function checkDependencies() { + if (function_exists('curl_init')) { + return true; + } else { + return array('curl'); + } + } + } diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index f3f3b3ed7f39b55e8b9fc30d628ab1c64747f1ce..b1d355323d9a078df9948f94367c0dc91ad6abb0 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -134,4 +134,18 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ } return $lastCtime; } + + /** + * check if smbclient is installed + */ + public static function checkDependencies() { + if (function_exists('shell_exec')) { + $output=shell_exec('command -v smbclient 2> /dev/null'); + if (!empty($output)) { + return true; + } + } + return array('smbclient'); + } + } diff --git a/apps/files_external/lib/smb_oc.php b/apps/files_external/lib/smb_oc.php new file mode 100644 index 0000000000000000000000000000000000000000..0c79c06c5df13863b68d295c4466f5d04234ae87 --- /dev/null +++ b/apps/files_external/lib/smb_oc.php @@ -0,0 +1,93 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage; + +require_once __DIR__ . '/../3rdparty/smb4php/smb.php'; + +class SMB_OC extends \OC\Files\Storage\SMB { + private $username_as_share; + + public function __construct($params) { + if (isset($params['host']) && \OC::$session->exists('smb-credentials')) { + $host=$params['host']; + $this->username_as_share = ($params['username_as_share'] === 'true'); + + $params_auth = \OC::$session->get('smb-credentials'); + $user = \OC::$session->get('loginname'); + $password = $params_auth['password']; + + $root=isset($params['root'])?$params['root']:'/'; + $share = ''; + + if ($this->username_as_share) { + $share = '/'.$user; + } elseif (isset($params['share'])) { + $share = $params['share']; + } else { + throw new \Exception(); + } + parent::__construct(array( + "user" => $user, + "password" => $password, + "host" => $host, + "share" => $share, + "root" => $root + )); + } else { + throw new \Exception(); + } + } + + public static function login( $params ) { + \OC::$session->set('smb-credentials', $params); + } + + public function isSharable($path) { + return false; + } + + public function test($isPersonal = true) { + if ($isPersonal) { + if ($this->stat('')) { + return true; + } + return false; + } else { + $smb = new \smb(); + $pu = $smb->parse_url($this->constructUrl('')); + + // Attempt to connect anonymously + $pu['user'] = ''; + $pu['pass'] = ''; + + // Share cannot be checked if dynamic + if ($this->username_as_share) { + if ($smb->look($pu)) { + return true; + } else { + return false; + } + } + if (!$pu['share']) { + return false; + } + + // The following error messages are expected due to anonymous login + $regexp = array( + '(NT_STATUS_ACCESS_DENIED)' => 'skip' + ) + $smb->getRegexp(); + + if ($smb->client("-d 0 " . escapeshellarg('//' . $pu['host'] . '/' . $pu['share']) . " -c exit", $pu, $regexp)) { + return true; + } else { + return false; + } + } + } +} diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index 7a56fcfc8b773fcf77b8c8e1769f5ff584a2be60..a202d3843cb212925b5ba82b5cea18064b653857 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -65,6 +65,18 @@ class Swift extends \OC\Files\Storage\Common { return $path; } + const SUBCONTAINER_FILE='.subcontainers'; + + /** + * translate directory path to container name + * @param string $path + * @return string + */ + private function getContainerName($path) { + $path=trim(trim($this->root, '/') . "/".$path, '/.'); + return str_replace('/', '\\', $path); + } + /** * @param string $path */ @@ -251,6 +263,10 @@ class Swift extends \OC\Files\Storage\Common { $mtime = $object->extra_headers['X-Object-Meta-Timestamp']; } + if (!empty($mtime)) { + $mtime = floor($mtime); + } + $stat = array(); $stat['size'] = $object->content_length; $stat['mtime'] = $mtime; @@ -370,7 +386,7 @@ class Swift extends \OC\Files\Storage\Common { 'X-Object-Meta-Timestamp' => $mtime ) ); - return $object->Update($settings); + return $object->UpdateMetadata($settings); } else { $object = $this->container->DataObject(); if (is_null($mtime)) { @@ -486,4 +502,16 @@ class Swift extends \OC\Files\Storage\Common { ), $tmpFile); unlink($tmpFile); } + + /** + * check if curl is installed + */ + public static function checkDependencies() { + if (function_exists('curl_init')) { + return true; + } else { + return array('curl'); + } + } + } diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 279ae716935994411e889bbadef270ecf362ef97..dc98dcfb8081189b81526df31f125ce4b4dbf87d 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -267,7 +267,7 @@ class DAV extends \OC\Files\Storage\Common { $curl = curl_init(); curl_setopt($curl, CURLOPT_USERPWD, $this->user . ':' . $this->password); - curl_setopt($curl, CURLOPT_URL, $this->createBaseUri() . str_replace(' ', '%20', $target)); + curl_setopt($curl, CURLOPT_URL, $this->createBaseUri() . $this->encodePath($target)); curl_setopt($curl, CURLOPT_BINARYTRANSFER, true); curl_setopt($curl, CURLOPT_INFILE, $source); // file pointer curl_setopt($curl, CURLOPT_INFILESIZE, filesize($path)); @@ -385,5 +385,16 @@ class DAV extends \OC\Files\Storage\Common { return false; } } + + /** + * check if curl is installed + */ + public static function checkDependencies() { + if (function_exists('curl_init')) { + return true; + } else { + return array('curl'); + } + } } diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index de44d3c86442180402458abc9be3dac82c6b94d5..0d04e35e7fef4a38d9c2bdf4a6ca64c9c1da86ee 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -1,149 +1,152 @@ -
-
+

t('External Storage')); ?>

- '')) print_unescaped(''.$_['dependencies'].''); ?> - '> - - - - - - - - '.$l->t('Applicable').''); ?> - - - - - array())); ?> - $mount): ?> - > - + + + + + + + +
t('Folder name')); ?>t('External storage')); ?>t('Configuration')); ?> 
- - - + '')) print_unescaped(''.$_['dependencies'].''); ?> + '> + + + + + + + + '.$l->t('Available for').''); ?> + + + + + array())); ?> + + > + + + + - - - - - - - + + - - - - - - -
t('Folder name')); ?>t('External storage')); ?>t('Configuration')); ?> 
+ + + + + - - - - $value): ?> - - - - - - - - - - - - - + + + + $value): ?> + + + + class="optional" + data-parameter="" + value="" + placeholder="" /> + + + + + + class="optional" + data-parameter="" + value="" + placeholder="" /> - - - + + + - ' - data-applicable-users=''> - - class="remove" - style="visibility:hidden;" - ><?php p($l->t('Delete')); ?>
-
+
' + data-applicable-users=''> + + class="remove" + style="visibility:hidden;" + ><?php p($l->t('Delete')); ?>
+
- -
- /> - + +
+ /> + -

class="hidden"> - t('Allow users to mount the following external storage')); ?>
- $backend): ?> - /> -
- - -

- -
+

class="hidden"> + t('Allow users to mount the following external storage')); ?>
+ $backend): ?> + /> +
+ + +

+
-
-

t('SSL root certificates'));?>

'> @@ -163,6 +166,5 @@ - diff --git a/apps/files_external/tests/dynamicmountconfig.php b/apps/files_external/tests/dynamicmountconfig.php new file mode 100644 index 0000000000000000000000000000000000000000..81a31e14c6071363adfbae60c5da722874613c34 --- /dev/null +++ b/apps/files_external/tests/dynamicmountconfig.php @@ -0,0 +1,103 @@ + + * + * 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 . + * + */ + +require_once __DIR__ . '/../../../lib/base.php'; + +require __DIR__ . '/../lib/config.php'; + +/** + * Class Test_Mount_Config_Dummy_Backend + */ +class Test_Mount_Config_Dummy_Backend { + public static $checkDependencies = true; + + public static function checkDependencies() { + return self::$checkDependencies; + } +} + +/** + * Class Test_Dynamic_Mount_Config + */ +class Test_Dynamic_Mount_Config extends \PHPUnit_Framework_TestCase { + + private $backup; + + public function testRegistration() { + + // second registration shall return false + $result = OC_Mount_Config::registerBackend('Test_Mount_Config_Dummy_Backend', array( + 'backend' => 'Test Dummy', + 'configuration' => array(), + 'has_dependencies' => true)); + + $this->assertTrue($result); + } + + public function testDependencyGetBackend() { + + // is the backend listed? + Test_Mount_Config_Dummy_Backend::$checkDependencies = true; + $backEnds = OC_Mount_Config::getBackends(); + $this->assertArrayHasKey('Test_Mount_Config_Dummy_Backend', $backEnds); + + // backend shall not be listed + Test_Mount_Config_Dummy_Backend::$checkDependencies = false; + + $backEnds = OC_Mount_Config::getBackends(); + $this->assertArrayNotHasKey('Test_Mount_Config_Dummy_Backend', $backEnds); + + } + + public function testCheckDependencies() { + + Test_Mount_Config_Dummy_Backend::$checkDependencies = true; + $message = OC_Mount_Config::checkDependencies(); + $this->assertEmpty($message); + + // backend shall not be listed + Test_Mount_Config_Dummy_Backend::$checkDependencies = array('dummy'); + + $message = OC_Mount_Config::checkDependencies(); + $this->assertEquals('
Note: "dummy" is not installed. Mounting of Test Dummy is not possible. Please ask your system administrator to install it.', + $message); + + } + + protected function setUp() { + + $this->backup = OC_Mount_Config::setUp(); + + // register dummy backend + $result = OC_Mount_Config::registerBackend('Test_Mount_Config_Dummy_Backend', array( + 'backend' => 'Test Dummy', + 'configuration' => array(), + 'has_dependencies' => true)); + + $this->assertTrue($result); + } + + protected function tearDown() + { + OC_Mount_Config::setUp($this->backup); + } +} diff --git a/apps/files_external/tests/mountconfig.php b/apps/files_external/tests/mountconfig.php index bf43bb31c3876c3fe6d108163abcc5646c078058..c89874c94d59ce32cd048b330804fae9875ab830 100644 --- a/apps/files_external/tests/mountconfig.php +++ b/apps/files_external/tests/mountconfig.php @@ -211,14 +211,52 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { } + /** + * Provider for testing configurations with different + * "applicable" values (all, user, groups) + */ + public function applicableConfigProvider() { + return array( + // applicable to "all" + array( + OC_Mount_Config::MOUNT_TYPE_USER, + 'all', + array( + 'users' => array('all'), + 'groups' => array() + ) + ), + // applicable to single user + array( + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER1, + array( + 'users' => array(self::TEST_USER1), + 'groups' => array() + ) + ), + // applicable to single group + array( + OC_Mount_Config::MOUNT_TYPE_GROUP, + self::TEST_GROUP1, + array( + 'users' => array(), + 'groups' => array(self::TEST_GROUP1) + ) + ), + ); + } + /** * Test reading and writing global config + * + * @dataProvider applicableConfigProvider */ - public function testReadWriteGlobalConfig() { - $mountType = OC_Mount_Config::MOUNT_TYPE_USER; - $applicable = 'all'; + public function testReadWriteGlobalConfig($mountType, $applicable, $expectApplicableArray) { + $mountType = $mountType; + $applicable = $applicable; $isPersonal = false; - $mountConfig = array( + $options = array( 'host' => 'smbhost', 'user' => 'smbuser', 'password' => 'smbpassword', @@ -231,7 +269,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { OC_Mount_Config::addMountPoint( '/ext', '\OC\Files\Storage\SMB', - $mountConfig, + $options, $mountType, $applicable, $isPersonal @@ -241,12 +279,13 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { // re-read config $config = OC_Mount_Config::getSystemMountPoints(); $this->assertEquals(1, count($config)); - $this->assertTrue(isset($config['ext'])); - $this->assertEquals('\OC\Files\Storage\SMB', $config['ext']['class']); - $savedMountConfig = $config['ext']['configuration']; - $this->assertEquals($mountConfig, $savedMountConfig); + $this->assertEquals('\OC\Files\Storage\SMB', $config[0]['class']); + $this->assertEquals('ext', $config[0]['mountpoint']); + $this->assertEquals($expectApplicableArray, $config[0]['applicable']); + $savedOptions = $config[0]['options']; + $this->assertEquals($options, $savedOptions); // key order needs to be preserved for the UI... - $this->assertEquals(array_keys($mountConfig), array_keys($savedMountConfig)); + $this->assertEquals(array_keys($options), array_keys($savedOptions)); } /** @@ -256,7 +295,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { $mountType = OC_Mount_Config::MOUNT_TYPE_USER; $applicable = self::TEST_USER1; $isPersonal = true; - $mountConfig = array( + $options = array( 'host' => 'smbhost', 'user' => 'smbuser', 'password' => 'smbpassword', @@ -269,7 +308,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { OC_Mount_Config::addMountPoint( '/ext', '\OC\Files\Storage\SMB', - $mountConfig, + $options, $mountType, $applicable, $isPersonal @@ -279,12 +318,12 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { // re-read config $config = OC_Mount_Config::getPersonalMountPoints(); $this->assertEquals(1, count($config)); - $this->assertTrue(isset($config['ext'])); - $this->assertEquals('\OC\Files\Storage\SMB', $config['ext']['class']); - $savedMountConfig = $config['ext']['configuration']; - $this->assertEquals($mountConfig, $savedMountConfig); + $this->assertEquals('\OC\Files\Storage\SMB', $config[0]['class']); + $this->assertEquals('ext', $config[0]['mountpoint']); + $savedOptions = $config[0]['options']; + $this->assertEquals($options, $savedOptions); // key order needs to be preserved for the UI... - $this->assertEquals(array_keys($mountConfig), array_keys($savedMountConfig)); + $this->assertEquals(array_keys($options), array_keys($savedOptions)); } /** @@ -362,7 +401,7 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { // re-read config, password was read correctly $config = OC_Mount_Config::getPersonalMountPoints(); - $savedMountConfig = $config['ext']['configuration']; + $savedMountConfig = $config[0]['options']; $this->assertEquals($mountConfig, $savedMountConfig); } @@ -475,4 +514,130 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { $this->assertEquals(0, count($mountPoints)); } } + + /** + * Test the same config for multiple users. + * The config will be merged by getSystemMountPoints(). + */ + public function testConfigMerging() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $isPersonal = false; + $options = array( + 'host' => 'smbhost', + 'user' => 'smbuser', + 'password' => 'smbpassword', + 'share' => 'smbshare', + 'root' => 'smbroot' + ); + + // write config + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $options, + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER1, + $isPersonal + ) + ); + + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $options, + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER2, + $isPersonal + ) + ); + + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $options, + OC_Mount_Config::MOUNT_TYPE_GROUP, + self::TEST_GROUP2, + $isPersonal + ) + ); + + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $options, + OC_Mount_Config::MOUNT_TYPE_GROUP, + self::TEST_GROUP1, + $isPersonal + ) + ); + + // re-read config + $config = OC_Mount_Config::getSystemMountPoints(); + $this->assertEquals(1, count($config)); + $this->assertEquals('\OC\Files\Storage\SMB', $config[0]['class']); + $this->assertEquals('ext', $config[0]['mountpoint']); + $this->assertEquals($options, $config[0]['options']); + $this->assertEquals(array(self::TEST_USER1, self::TEST_USER2), $config[0]['applicable']['users']); + $this->assertEquals(array(self::TEST_GROUP2, self::TEST_GROUP1), $config[0]['applicable']['groups']); + } + + /** + * Create then re-read mount points configs where the mount points + * have the same path, the config must NOT be merged. + */ + public function testRereadMountpointWithSamePath() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $isPersonal = false; + $options1 = array( + 'host' => 'smbhost', + 'user' => 'smbuser', + 'password' => 'smbpassword', + 'share' => 'smbshare', + 'root' => 'smbroot' + ); + + // write config + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $options1, + $mountType, + self::TEST_USER1, + $isPersonal + ) + ); + + $options2 = array( + 'host' => 'anothersmbhost', + 'user' => 'anothersmbuser', + 'password' => 'anothersmbpassword', + 'share' => 'anothersmbshare', + 'root' => 'anothersmbroot' + ); + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $options2, + $mountType, + self::TEST_USER2, + $isPersonal + ) + ); + + // re-read config + $config = OC_Mount_Config::getSystemMountPoints(); + $this->assertEquals(2, count($config)); + $this->assertEquals('\OC\Files\Storage\SMB', $config[0]['class']); + $this->assertEquals('ext', $config[0]['mountpoint']); + $this->assertEquals($options1, $config[0]['options']); + $this->assertEquals('\OC\Files\Storage\SMB', $config[1]['class']); + $this->assertEquals('ext', $config[1]['mountpoint']); + $this->assertEquals($options2, $config[1]['options']); + } } diff --git a/apps/files_sharing/ajax/list.php b/apps/files_sharing/ajax/list.php new file mode 100644 index 0000000000000000000000000000000000000000..4b645496253f704567b31e5895289e82dac105b0 --- /dev/null +++ b/apps/files_sharing/ajax/list.php @@ -0,0 +1,91 @@ + + * + * 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 . + * + */ + +// only need filesystem apps +$RUNTIME_APPTYPES=array('filesystem'); + +// Init owncloud + +if(!\OC_App::isEnabled('files_sharing')){ + exit; +} + +if(!isset($_GET['t'])){ + \OC_Response::setStatus(400); //400 Bad Request + \OC_Log::write('core-preview', 'No token parameter was passed', \OC_Log::DEBUG); + exit; +} + +$token = $_GET['t']; + +$password = null; +if (isset($_POST['password'])) { + $password = $_POST['password']; +} + +$relativePath = null; +if (isset($_GET['dir'])) { + $relativePath = $_GET['dir']; +} + +$data = \OCA\Files_Sharing\Helper::setupFromToken($token, $relativePath, $password); + +$linkItem = $data['linkItem']; +// Load the files +$dir = $data['realPath']; + +$dir = \OC\Files\Filesystem::normalizePath($dir); +if (!\OC\Files\Filesystem::is_dir($dir . '/')) { + \OC_Response::setStatus(404); + \OCP\JSON::error(array('success' => false)); + exit(); +} + +$data = array(); +$baseUrl = OCP\Util::linkTo('files_sharing', 'index.php') . '?t=' . urlencode($token) . '&dir='; + +// make filelist +$files = \OCA\Files\Helper::getFiles($dir); + +$formattedFiles = array(); +foreach ($files as $file) { + $entry = \OCA\Files\Helper::formatFileInfo($file); + unset($entry['directory']); // for now + $entry['permissions'] = \OCP\PERMISSION_READ; + $formattedFiles[] = $entry; +} + +$data['directory'] = $relativePath; +$data['files'] = $formattedFiles; +$data['dirToken'] = $linkItem['token']; + +$permissions = $linkItem['permissions']; + +// if globally disabled +if (OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes') === 'no') { + // only allow reading + $permissions = \OCP\PERMISSION_READ; +} + +$data['permissions'] = $permissions; + +OCP\JSON::success(array('data' => $data)); diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 4b716e764f4c343255f41cf94817ee531cbc4e12..ab32108ea25f9668ee2ee6ffec704d3a7b5a2ced 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -71,19 +71,6 @@ if (version_compare($installedVersion, '0.3', '<')) { } // clean up oc_share table from files which are no longer exists -if (version_compare($installedVersion, '0.3.5', '<')) { - - // get all shares where the original file no longer exists - $findShares = \OC_DB::prepare('SELECT `file_source` FROM `*PREFIX*share` LEFT JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` WHERE `*PREFIX*filecache`.`fileid` IS NULL AND `*PREFIX*share`.`item_type` IN (\'file\', \'folder\')'); - $sharesFound = $findShares->execute(array())->fetchAll(); - - // delete those shares from the oc_share table - if (is_array($sharesFound) && !empty($sharesFound)) { - $delArray = array(); - foreach ($sharesFound as $share) { - $delArray[] = $share['file_source']; - } - $removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `file_source` IN (?)'); - $result = $removeShares->execute(array(implode(',', $delArray))); - } +if (version_compare($installedVersion, '0.3.5.6', '<')) { + \OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate(); } diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version index 09e9157034c28c1c2516f005c9306248219630c4..8f91d33378ed1aa457f6edb4b629f3844829658f 100644 --- a/apps/files_sharing/appinfo/version +++ b/apps/files_sharing/appinfo/version @@ -1 +1 @@ -0.3.5 \ No newline at end of file +0.3.5.6 diff --git a/apps/files_sharing/css/mobile.css b/apps/files_sharing/css/mobile.css index 7d2116d190dc542564310b9ef8618304b8e8f242..333c4c77fc999c6acd16723d900384a1d3d110ee 100644 --- a/apps/files_sharing/css/mobile.css +++ b/apps/files_sharing/css/mobile.css @@ -1,4 +1,4 @@ -@media only screen and (max-width: 600px) { +@media only screen and (max-width: 768px) { /* make header scroll up for single shares, more view of content on small screens */ #header.share-file { @@ -45,5 +45,13 @@ table td.filename .nametext { display: none; } +/* ellipsis on file names */ +.nametext { + width: 60%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + } diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css index 5246a4b2fec1dd6dde2ec8153c3c27966d8c60a8..f0b9b04491fdbb0591f923a64aa79712506313a8 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -35,6 +35,11 @@ body { background: #fff; text-align: center; margin: 45px auto 0; + min-height: 150px; +} + +#preview .notCreatable { + display: none; } #noPreview { diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 06c168969deac4620ba42600ad18e8e645c0c0e0..9ce8985f1fd28e381e9a45ae515c0648a714d302 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -8,16 +8,7 @@ * */ -/* global OC, FileList, FileActions */ - -// Override download path to files_sharing/public.php -function fileDownloadPath(dir, file) { - var url = $('#downloadURL').val(); - if (url.indexOf('&path=') != -1) { - url += '/'+file; - } - return url; -} +/* global OC, FileActions, FileList, Files */ $(document).ready(function() { @@ -31,31 +22,43 @@ $(document).ready(function() { action($('#filename').val()); } } - FileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function(filename) { - var tr = FileList.findFileEl(filename); - if (tr.length > 0) { - window.location = $(tr).find('a.name').attr('href'); - } - }); + } - // override since the format is different - FileList.getDownloadUrl = function(filename, dir) { - if ($.isArray(filename)) { - filename = JSON.stringify(filename); - } - var path = dir || FileList.getCurrentDirectory(); - var params = { - service: 'files', - t: $('#sharingToken').val(), - path: path, - download: null - }; - if (filename) { - params.files = filename; - } - return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); + // override since the format is different + Files.getDownloadUrl = function(filename, dir) { + if ($.isArray(filename)) { + filename = JSON.stringify(filename); + } + var path = dir || FileList.getCurrentDirectory(); + var params = { + service: 'files', + t: $('#sharingToken').val(), + path: path, + files: filename, + download: null }; - } + return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); + }; + + Files.getAjaxUrl = function(action, params) { + params = params || {}; + params.t = $('#sharingToken').val(); + return OC.filePath('files_sharing', 'ajax', action + '.php') + '?' + OC.buildQueryString(params); + }; + + FileList.linkTo = function(dir) { + var params = { + service: 'files', + t: $('#sharingToken').val(), + dir: dir + }; + return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); + }; + + Files.generatePreviewUrl = function(urlSpec) { + urlSpec.t = $('#dirToken').val(); + return OC.generateUrl('/apps/files_sharing/ajax/publicpreview.php?') + $.param(urlSpec); + }; var file_upload_start = $('#file_upload_start'); file_upload_start.on('fileuploadadd', function(e, data) { diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 9f0ed12f935cce15439de22c0dcd5544537c396f..3c7c9239a6cbf3f870a3a253936ffeb27983210d 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -1,15 +1,35 @@ +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global OC, t, FileList, FileActions */ $(document).ready(function() { var disableSharing = $('#disableSharing').data('status'), sharesLoaded = false; if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !disableSharing) { + var oldCreateRow = FileList._createRow; + FileList._createRow = function(fileData) { + var tr = oldCreateRow.apply(this, arguments); + if (fileData.shareOwner) { + tr.attr('data-share-owner', fileData.shareOwner); + } + return tr; + }; + $('#fileList').on('fileActionsReady',function(){ - var allShared = $('#fileList').find('[data-share-owner]').find('[data-Action="Share"]'); + var allShared = $('#fileList').find('[data-share-owner] [data-Action="Share"]'); allShared.addClass('permanent'); allShared.find('span').text(function(){ - $owner = $(this).closest('tr').attr('data-share-owner'); + var $owner = $(this).closest('tr').attr('data-share-owner'); return ' ' + t('files_sharing', 'Shared by {owner}', {owner: $owner}); }); @@ -25,11 +45,6 @@ $(document).ready(function() { }); FileActions.register('all', 'Share', OC.PERMISSION_READ, OC.imagePath('core', 'actions/share'), function(filename) { - var dir = $('#dir').val(); - var item = dir + '/' + filename; - if (dir == '/') { - item = dir + filename; - } var tr = FileList.findFileEl(filename); var itemType = 'file'; if ($(tr).data('type') == 'dir') { diff --git a/apps/files_sharing/l10n/ast.php b/apps/files_sharing/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..02a2f6fb628975c2da861acebd11ba5b1c84a7a9 --- /dev/null +++ b/apps/files_sharing/l10n/ast.php @@ -0,0 +1,6 @@ + "Compartíu por {owner}", +"Password" => "Contraseña" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/et_EE.php b/apps/files_sharing/l10n/et_EE.php index af5891fcc7f23781ea7fcc1248f2f40e659281de..7150f05da227ffa4b1c820a82c760075ea3fbdb1 100644 --- a/apps/files_sharing/l10n/et_EE.php +++ b/apps/files_sharing/l10n/et_EE.php @@ -11,6 +11,7 @@ $TRANSLATIONS = array( "sharing is disabled" => "jagamine on peatatud", "For more info, please ask the person who sent this link." => "Täpsema info saamiseks palun pöördu lingi saatnud isiku poole.", "shared by %s" => "jagas %s", +"Download %s" => "Laadi alla %s", "Direct link" => "Otsene link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/sk_SK.php b/apps/files_sharing/l10n/sk_SK.php index 4e9856da4a7698d4684e32eacd8c5a7cadcd2151..6856c0591f401cafe0a715c674e50c48e6ca1ea4 100644 --- a/apps/files_sharing/l10n/sk_SK.php +++ b/apps/files_sharing/l10n/sk_SK.php @@ -11,6 +11,7 @@ $TRANSLATIONS = array( "sharing is disabled" => "zdieľanie je zakázané", "For more info, please ask the person who sent this link." => "Pre viac informácií kontaktujte osobu, ktorá vám poslala tento odkaz.", "shared by %s" => "Zdieľa %s", +"Download %s" => "Stiahnuť %s", "Direct link" => "Priama linka" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/apps/files_sharing/l10n/sv.php b/apps/files_sharing/l10n/sv.php index 2d037f9186e3d346e17ca09353d47acf30d75790..94b7edf6977f80d3267cf32a1d3f58e14374b48a 100644 --- a/apps/files_sharing/l10n/sv.php +++ b/apps/files_sharing/l10n/sv.php @@ -10,6 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "giltighet för länken har gått ut", "sharing is disabled" => "delning är inaktiverat", "For more info, please ask the person who sent this link." => "För mer information, kontakta den person som skickade den här länken.", +"shared by %s" => "delad av %s", +"Download %s" => "Ladda ner %s", "Direct link" => "Direkt länk" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 01db29d72e2888652101ac158ec7d7d2eab45269..eeb62c3cce2c0c6f4348010cde2130163e1fcd94 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -20,6 +20,7 @@ */ namespace OC\Files\Cache; + use OCP\Share_Backend_Collection; /** @@ -50,7 +51,7 @@ class Shared_Cache extends Cache { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); $mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']); if (is_array($mount)) { - $fullPath = $mount[key($mount)]->getMountPoint().$source['path']; + $fullPath = $mount[key($mount)]->getMountPoint() . $source['path']; list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); if ($storage) { $this->files[$target] = $internalPath; @@ -75,7 +76,7 @@ class Shared_Cache extends Cache { /** * get the stored metadata of a file or folder * - * @param string/int $file + * @param string /int $file * @return array */ public function get($file) { @@ -95,8 +96,8 @@ class Shared_Cache extends Cache { } else { $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,' - .' `size`, `mtime`, `encrypted`, `unencrypted_size`' - .' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + . ' `size`, `mtime`, `encrypted`, `unencrypted_size`' + . ' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); $result = $query->execute(array($file)); $data = $result->fetchRow(); $data['fileid'] = (int)$data['fileid']; @@ -288,8 +289,7 @@ class Shared_Cache extends Cache { foreach ($files as $file) { if ($file['mimetype'] === 'httpd/unix-directory') { $exploreDirs[] = ltrim($dir . '/' . $file['name'], '/'); - } - else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) { + } else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) { // usersPath not reliable //$file['path'] = $file['usersPath']; $file['path'] = ltrim($dir . '/' . $file['name'], '/'); @@ -344,8 +344,6 @@ class Shared_Cache extends Cache { if ($row['encrypted'] or ($row['unencrypted_size'] > 0 and $row['mimetype'] === 'httpd/unix-directory')) { $row['encrypted_size'] = $row['size']; $row['size'] = $row['unencrypted_size']; - } else { - $row['size'] = $row['size']; } $files[] = $row; } @@ -402,4 +400,48 @@ class Shared_Cache extends Cache { return false; } + /** + * get the path of a file on this storage by it's id + * + * @param int $id + * @param string $pathEnd (optional) used internally for recursive calls + * @return string | null + */ + public function getPathById($id, $pathEnd = '') { + // direct shares are easy + if ($path = $this->getShareById($id)) { + return $path . $pathEnd; + } else { + // if the item is a direct share we try and get the path of the parent and append the name of the item to it + list($parent, $name) = $this->getParentInfo($id); + if ($parent > 0) { + return $this->getPathById($parent, '/' . $name . $pathEnd); + } else { + return null; + } + } + } + + private function getShareById($id) { + $item = \OCP\Share::getItemSharedWithBySource('file', $id); + if ($item) { + return trim($item['file_target'], '/'); + } + $item = \OCP\Share::getItemSharedWithBySource('folder', $id); + if ($item) { + return trim($item['file_target'], '/'); + } + return null; + } + + private function getParentInfo($id) { + $sql = 'SELECT `parent`, `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?'; + $query = \OC_DB::prepare($sql); + $result = $query->execute(array($id)); + if ($row = $result->fetchRow()) { + return array($row['parent'], $row['name']); + } else { + return array(-1, ''); + } + } } diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php new file mode 100644 index 0000000000000000000000000000000000000000..b602fe3599d0888c27ef589f52d774f1c904a15b --- /dev/null +++ b/apps/files_sharing/lib/helper.php @@ -0,0 +1,114 @@ + false)); + exit(); + } + + if (!isset($linkItem['item_type'])) { + \OCP\Util::writeLog('share', 'No item type set for share id: ' . $linkItem['id'], \OCP\Util::ERROR); + \OC_Response::setStatus(404); + \OCP\JSON::error(array('success' => false)); + exit(); + } + + if (isset($linkItem['share_with'])) { + if (!self::authenticate($linkItem, $password)) { + \OC_Response::setStatus(403); + \OCP\JSON::error(array('success' => false)); + exit(); + } + } + + $basePath = $path; + $rootName = basename($path); + + if ($relativePath !== null && \OC\Files\Filesystem::isReadable($basePath . $relativePath)) { + $path .= \OC\Files\Filesystem::normalizePath($relativePath); + } + + return array( + 'linkItem' => $linkItem, + 'basePath' => $basePath, + 'realPath' => $path + ); + } + + /** + * Authenticate link item with the given password + * or with the session if no password was given. + * @param array $linkItem link item array + * @param string $password optional password + * + * @return true if authorized, false otherwise + */ + public static function authenticate($linkItem, $password) { + if ($password !== null) { + if ($linkItem['share_type'] == \OCP\Share::SHARE_TYPE_LINK) { + // Check Password + $forcePortable = (CRYPT_BLOWFISH != 1); + $hasher = new PasswordHash(8, $forcePortable); + if (!($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), + $linkItem['share_with']))) { + return false; + } else { + // Save item id in session for future requests + \OC::$session->set('public_link_authenticated', $linkItem['id']); + } + } else { + \OCP\Util::writeLog('share', 'Unknown share type '.$linkItem['share_type'] + .' for share id '.$linkItem['id'], \OCP\Util::ERROR); + return false; + } + + } + else { + // not authenticated ? + if ( ! \OC::$session->exists('public_link_authenticated') + || \OC::$session->get('public_link_authenticated') !== $linkItem['id']) { + return false; + } + } + return true; + } +} diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index 23ebc9fb811c37de046f080bd7acb508ca6dd638..e3a7679292d0e5aecf0e00287b70e1e4918a582a 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -135,4 +135,19 @@ class Shared_Updater { } } + /** + * clean up oc_share table from files which are no longer exists + * + * This fixes issues from updates from files_sharing < 0.3.5.6 (ownCloud 4.5) + * It will just be called during the update of the app + */ + static public function fixBrokenSharesOnAppUpdate() { + // delete all shares where the original file no longer exists + $findAndRemoveShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share` ' . + 'WHERE `file_source` NOT IN ( ' . + 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `item_type` IN (\'file\', \'folder\'))' + ); + $findAndRemoveShares->execute(array()); + } + } diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index fe61dd4d5a048d0a128597744c9ceaf31ae5a9c9..ce51eca6ddb8928bfbfbbec9f99cd1abe291d131 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -11,31 +11,6 @@ if ($appConfig->getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { exit(); } -function fileCmp($a, $b) { - if ($a['type'] == 'dir' and $b['type'] != 'dir') { - return -1; - } elseif ($a['type'] != 'dir' and $b['type'] == 'dir') { - return 1; - } else { - return strnatcasecmp($a['name'], $b['name']); - } -} - -function determineIcon($file, $sharingRoot, $sharingToken) { - // for folders we simply reuse the files logic - if($file['type'] == 'dir') { - return \OCA\Files\Helper::determineIcon($file); - } - - $relativePath = substr($file['path'], 6); - $relativePath = substr($relativePath, strlen($sharingRoot)); - if($file['isPreviewAvailable']) { - return OCP\publicPreview_icon($relativePath, $sharingToken) . '&c=' . $file['etag']; - } - $icon = OCP\mimetype_icon($file['mimetype']); - return substr($icon, 0, -3) . 'svg'; -} - if (isset($_GET['t'])) { $token = $_GET['t']; $linkItem = OCP\Share::getShareByToken($token, false); @@ -153,13 +128,6 @@ if (isset($path)) { $tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); $tmpl->assign('dirToken', $linkItem['token']); $tmpl->assign('sharingToken', $token); - $allowPublicUploadEnabled = (bool) ($linkItem['permissions'] & OCP\PERMISSION_CREATE); - if ($appConfig->getValue('core', 'shareapi_allow_public_upload', 'yes') === 'no') { - $allowPublicUploadEnabled = false; - } - if ($linkItem['item_type'] !== 'folder') { - $allowPublicUploadEnabled = false; - } $urlLinkIdentifiers= (isset($token)?'&t='.$token:'') .(isset($_GET['dir'])?'&dir='.$_GET['dir']:'') @@ -170,64 +138,18 @@ if (isset($path)) { OCP\Util::addStyle('files', 'files'); OCP\Util::addStyle('files', 'upload'); + OCP\Util::addScript('files', 'breadcrumb'); OCP\Util::addScript('files', 'files'); OCP\Util::addScript('files', 'filelist'); OCP\Util::addscript('files', 'keyboardshortcuts'); $files = array(); $rootLength = strlen($basePath) + 1; - $totalSize = 0; - foreach (\OC\Files\Filesystem::getDirectoryContent($path) as $i) { - $totalSize += $i['size']; - $i['date'] = OCP\Util::formatDate($i['mtime']); - if ($i['type'] == 'file') { - $fileinfo = pathinfo($i['name']); - $i['basename'] = $fileinfo['filename']; - if (!empty($fileinfo['extension'])) { - $i['extension'] = '.' . $fileinfo['extension']; - } else { - $i['extension'] = ''; - } - } - $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($i['mimetype']); - $i['directory'] = $getPath; - $i['permissions'] = OCP\PERMISSION_READ; - $i['icon'] = determineIcon($i, $basePath, $token); - $files[] = $i; - } - usort($files, "fileCmp"); - - // Make breadcrumb - $breadcrumb = array(); - $pathtohere = ''; - foreach (explode('/', $getPath) as $i) { - if ($i != '') { - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); - } - } - $list = new OCP\Template('files', 'part.list', ''); - $list->assign('files', $files); - $list->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path='); - $list->assign('downloadURL', - OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path='); - $list->assign('isPublic', true); - $list->assign('sharingtoken', $token); - $list->assign('sharingroot', $basePath); - $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); - $breadcrumbNav->assign('breadcrumb', $breadcrumb); - $breadcrumbNav->assign('rootBreadCrumb', $rootName); - $breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path='); $maxUploadFilesize=OCP\Util::maxUploadFilesize($path); - $fileHeader = (!isset($files) or count($files) > 0); - $emptyContent = ($allowPublicUploadEnabled and !$fileHeader); $freeSpace=OCP\Util::freeSpace($path); $uploadLimit=OCP\Util::uploadLimit(); $folder = new OCP\Template('files', 'index', ''); - $folder->assign('fileList', $list->fetchPage()); - $folder->assign('breadcrumb', $breadcrumbNav->fetchPage()); $folder->assign('dir', $getPath); - $folder->assign('isCreatable', $allowPublicUploadEnabled); $folder->assign('dirToken', $linkItem['token']); $folder->assign('permissions', OCP\PERMISSION_READ); $folder->assign('isPublic',true); @@ -239,15 +161,11 @@ if (isset($path)) { $folder->assign('uploadLimit', $uploadLimit); // PHP upload limit $folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); $folder->assign('usedSpacePercent', 0); - $folder->assign('fileHeader', $fileHeader); $folder->assign('disableSharing', true); $folder->assign('trash', false); - $folder->assign('emptyContent', $emptyContent); - $folder->assign('ajaxLoad', false); $tmpl->assign('folder', $folder->fetchPage()); $maxInputFileSize = OCP\Config::getSystemValue('maxZipInputSize', OCP\Util::computerFileSize('800 MB')); - $allowZip = OCP\Config::getSystemValue('allowZipDownload', true) - && ( $maxInputFileSize === 0 || $totalSize <= $maxInputFileSize); + $allowZip = OCP\Config::getSystemValue('allowZipDownload', true); $tmpl->assign('allowZipDownload', intval($allowZip)); $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path=' . urlencode($getPath)); diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php index e2bbb548182498f8c08b6d3c551cefb45fd3a91f..c7a848315ac8e7231ab151119ae72611e89f69f2 100644 --- a/apps/files_sharing/tests/api.php +++ b/apps/files_sharing/tests/api.php @@ -878,6 +878,29 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $this->assertSame($expectedResult, $shareApiDummy->correctPathTest($path, $folder)); } + /** + * @expectedException \Exception + */ + public function testShareNonExisting() { + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); + + $id = PHP_INT_MAX - 1; + \OCP\Share::shareItem('file', $id, \OCP\Share::SHARE_TYPE_LINK, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); + } + + /** + * @expectedException \Exception + */ + public function testShareNotOwner() { + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); + \OC\Files\Filesystem::file_put_contents('foo.txt', 'bar'); + $info = \OC\Files\Filesystem::getFileInfo('foo.txt'); + + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); + + \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); + } + } /** @@ -886,5 +909,5 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { class TestShareApi extends \OCA\Files\Share\Api { public function correctPathTest($path, $folder) { return self::correctPath($path, $folder); -} + } } diff --git a/apps/files_sharing/tests/cache.php b/apps/files_sharing/tests/cache.php index a75e1860527809e9292d21c6ca4a26feda3ffc8e..47969833ab515bb01af818f5d7101ff4f10740b6 100644 --- a/apps/files_sharing/tests/cache.php +++ b/apps/files_sharing/tests/cache.php @@ -246,4 +246,43 @@ class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base { } } + public function testGetPathByIdDirectShare() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::file_put_contents('test.txt', 'foo'); + $info = \OC\Files\Filesystem::getFileInfo('test.txt'); + \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, \OCP\PERMISSION_ALL); + \OC_Util::tearDownFS(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/Shared/test.txt')); + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/Shared/test.txt'); + /** + * @var \OC\Files\Storage\Shared $sharedStorage + */ + + $sharedCache = $sharedStorage->getCache(); + $this->assertEquals('test.txt', $sharedCache->getPathById($info->getId())); + } + + public function testGetPathByIdShareSubFolder() { + self::loginHelper(self::TEST_FILES_SHARING_API_USER1); + \OC\Files\Filesystem::mkdir('foo'); + \OC\Files\Filesystem::mkdir('foo/bar'); + \OC\Files\Filesystem::touch('foo/bar/test.txt', 'bar'); + $folderInfo = \OC\Files\Filesystem::getFileInfo('foo'); + $fileInfo = \OC\Files\Filesystem::getFileInfo('foo/bar/test.txt'); + \OCP\Share::shareItem('folder', $folderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER2, \OCP\PERMISSION_ALL); + \OC_Util::tearDownFS(); + + self::loginHelper(self::TEST_FILES_SHARING_API_USER2); + $this->assertTrue(\OC\Files\Filesystem::file_exists('/Shared/foo')); + list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/Shared/foo'); + /** + * @var \OC\Files\Storage\Shared $sharedStorage + */ + + $sharedCache = $sharedStorage->getCache(); + $this->assertEquals('foo', $sharedCache->getPathById($folderInfo->getId())); + $this->assertEquals('foo/bar/test.txt', $sharedCache->getPathById($fileInfo->getId())); + } } diff --git a/apps/files_sharing/tests/updater.php b/apps/files_sharing/tests/updater.php new file mode 100644 index 0000000000000000000000000000000000000000..79ae4879b645d1aa55612ae5b2fdfe1abf4a7fe7 --- /dev/null +++ b/apps/files_sharing/tests/updater.php @@ -0,0 +1,91 @@ + + * + * 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 . + * + */ + +/** + * Class Test_Files_Sharing_Updater + */ +class Test_Files_Sharing_Updater extends \PHPUnit_Framework_TestCase { + + function setUp() { + // some previous tests didn't clean up and therefore this has to be done here + // FIXME: DIRTY HACK - TODO: find tests, that don't clean up and fix it there + $this->tearDown(); + + // add items except one - because this is the test case for the broken share table + $addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` (`storage`, `path_hash`, ' . + '`parent`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`) ' . + 'VALUES (1, ?, 1, 1, 1, 1, 1, 1)'); + $items = array(1, 3); + $fileIds = array(); + foreach($items as $item) { + // the number is used as path_hash + $addItems->execute(array($item)); + $fileIds[] = \OC_DB::insertId('*PREFIX*filecache'); + } + + $addShares = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`file_source`, `item_type`, `uid_owner`) VALUES (?, \'file\', 1)'); + // the number is used as item_source + $addShares->execute(array($fileIds[0])); + $addShares->execute(array(200)); // id of "deleted" file + $addShares->execute(array($fileIds[1])); + } + + function tearDown() { + $removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share`'); + $removeShares->execute(); + $removeItems = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache`'); + $removeItems->execute(); + } + + /** + * @medium + */ + function testRemoveBrokenShares() { + // check if there are just 3 shares (see setUp - precondition: empty table) + $countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`'); + $result = $countShares->execute()->fetchOne(); + $this->assertEquals(3, $result); + + // check if there are just 2 items (see setUp - precondition: empty table) + $countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`'); + $result = $countItems->execute()->fetchOne(); + $this->assertEquals(2, $result); + + // execute actual code which should be tested + \OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate(); + + // check if there are just 2 shares (one gets killed by the code as there is no filecache entry for this) + $countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`'); + $result = $countShares->execute()->fetchOne(); + $this->assertEquals(2, $result); + + // check if the share of file '200' is removed as there is no entry for this in filecache table + $countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share` WHERE `file_source` = 200'); + $result = $countShares->execute()->fetchOne(); + $this->assertEquals(0, $result); + + // check if there are just 2 items + $countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`'); + $result = $countItems->execute()->fetchOne(); + $this->assertEquals(2, $result); + } +} diff --git a/apps/files_trashbin/ajax/list.php b/apps/files_trashbin/ajax/list.php index 124a236bcbd505ea904181e4f2ce909766bb28b2..89a5511452449ccb416cbac15ca2952c723c19a7 100644 --- a/apps/files_trashbin/ajax/list.php +++ b/apps/files_trashbin/ajax/list.php @@ -1,30 +1,11 @@ assign('breadcrumb', $breadcrumb, false); - $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir='); - $breadcrumbNav->assign('home', OCP\Util::linkTo('files', 'index.php')); - - $data['breadcrumb'] = $breadcrumbNav->fetchPage(); -} - // make filelist try { $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); @@ -33,19 +14,11 @@ try { exit(); } -$dirlisting = false; -if ($dir && $dir !== '/') { - $dirlisting = true; -} - $encodedDir = \OCP\Util::encodePath($dir); -$list = new OCP\Template('files_trashbin', 'part.list', ''); -$list->assign('files', $files, false); -$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$encodedDir); -$list->assign('downloadURL', OCP\Util::linkToRoute('download', array('file' => '/'))); -$list->assign('dirlisting', $dirlisting); -$list->assign('disableDownloadActions', true); -$data['files'] = $list->fetchPage(); + +$data['permissions'] = 0; +$data['directory'] = $dir; +$data['files'] = \OCA\Files_Trashbin\Helper::formatFileInfos($files); OCP\JSON::success(array('data' => $data)); diff --git a/apps/files_trashbin/ajax/preview.php b/apps/files_trashbin/ajax/preview.php index ce64d9ecc9f962bbc4532f6d53729b517e0be00c..32905b2a71ce41d54df8bf72d456ef80cf8d1e58 100644 --- a/apps/files_trashbin/ajax/preview.php +++ b/apps/files_trashbin/ajax/preview.php @@ -34,7 +34,7 @@ try{ if ($view->is_dir($file)) { $mimetype = 'httpd/unix-directory'; } else { - $pathInfo = pathinfo($file); + $pathInfo = pathinfo(ltrim($file, '/')); $fileName = $pathInfo['basename']; // if in root dir if ($pathInfo['dirname'] === '.') { diff --git a/apps/files_trashbin/ajax/undelete.php b/apps/files_trashbin/ajax/undelete.php index 9c3ccba7ed8812021aa26520025ffdc7844d4f32..2b00078669ee42074ae9d63e8b1fac1bd43eaeb3 100644 --- a/apps/files_trashbin/ajax/undelete.php +++ b/apps/files_trashbin/ajax/undelete.php @@ -19,7 +19,7 @@ if (isset($_POST['allfiles']) and $_POST['allfiles'] === 'true') { foreach (OCA\Files_Trashbin\Helper::getTrashFiles($dir) as $file) { $fileName = $file['name']; if (!$dirListing) { - $fileName .= '.d' . $file['timestamp']; + $fileName .= '.d' . $file['mtime']; } $list[] = $fileName; } diff --git a/apps/files_trashbin/css/trash.css b/apps/files_trashbin/css/trash.css index 97819f4e80b5b15fcd4e31077821075aa907af7c..7ca3e355fc211bf02aabb20bb036710279d52a6e 100644 --- a/apps/files_trashbin/css/trash.css +++ b/apps/files_trashbin/css/trash.css @@ -1,3 +1,4 @@ -#fileList td a.file, #fileList td a.file span { +#fileList tr[data-type="file"] td a.name, +#fileList tr[data-type="file"] td a.name span { cursor: default; } diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php index f0c5b0508b8440285ccca7e89ed0e1fedf98e882..e63fe1e4188e46e2052818e53b3873d5b6b8d1a0 100644 --- a/apps/files_trashbin/index.php +++ b/apps/files_trashbin/index.php @@ -11,6 +11,7 @@ $tmpl = new OCP\Template('files_trashbin', 'index', 'user'); OCP\Util::addStyle('files', 'files'); OCP\Util::addStyle('files_trashbin', 'trash'); +OCP\Util::addScript('files', 'breadcrumb'); OCP\Util::addScript('files', 'filelist'); // filelist overrides OCP\Util::addScript('files_trashbin', 'filelist'); @@ -34,48 +35,7 @@ if ($isIE8 && isset($_GET['dir'])){ exit(); } -$ajaxLoad = false; - -if (!$isIE8){ - try { - $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); - } catch (Exception $e) { - header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php')); - exit(); - } -} -else{ - $files = array(); - $ajaxLoad = true; -} - -$dirlisting = false; -if ($dir && $dir !== '/') { - $dirlisting = true; -} - -$breadcrumb = \OCA\Files_Trashbin\Helper::makeBreadcrumb($dir); - -$breadcrumbNav = new OCP\Template('files_trashbin', 'part.breadcrumb', ''); -$breadcrumbNav->assign('breadcrumb', $breadcrumb); -$breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir='); -$breadcrumbNav->assign('home', OCP\Util::linkTo('files', 'index.php')); - -$list = new OCP\Template('files_trashbin', 'part.list', ''); -$list->assign('files', $files); - -$encodedDir = \OCP\Util::encodePath($dir); -$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$encodedDir); -$list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file='.$encodedDir); -$list->assign('dirlisting', $dirlisting); -$list->assign('disableDownloadActions', true); - -$tmpl->assign('dirlisting', $dirlisting); -$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage()); -$tmpl->assign('fileList', $list->fetchPage()); -$tmpl->assign('files', $files); $tmpl->assign('dir', $dir); $tmpl->assign('disableSharing', true); -$tmpl->assign('ajaxLoad', true); $tmpl->printPage(); diff --git a/apps/files_trashbin/js/disableDefaultActions.js b/apps/files_trashbin/js/disableDefaultActions.js index afa80cacd6b04756f9abf296ca0908061561bd6f..50ceaf4696fe1aa041dfea3c29d02b8e513dc6da 100644 --- a/apps/files_trashbin/js/disableDefaultActions.js +++ b/apps/files_trashbin/js/disableDefaultActions.js @@ -1,4 +1,3 @@ /* disable download and sharing actions */ var disableDownloadActions = true; -var disableSharing = true; var trashBinApp = true; diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js index a88459b0a9aaa016b4980d731a5cffeba9eb4bd0..7795daf2775bbc609c82c7dfcac868d565cccc48 100644 --- a/apps/files_trashbin/js/filelist.js +++ b/apps/files_trashbin/js/filelist.js @@ -1,61 +1,78 @@ -/* globals OC, FileList, t */ -// override reload with own ajax call -FileList.reload = function(){ - FileList.showMask(); - if (FileList._reloadCall){ - FileList._reloadCall.abort(); - } - $.ajax({ - url: OC.filePath('files_trashbin','ajax','list.php'), - data: { - dir : $('#dir').val(), - breadcrumb: true - }, - error: function(result) { - FileList.reloadCallback(result); - }, - success: function(result) { - FileList.reloadCallback(result); +/* global OC, t, FileList */ +(function() { + FileList.appName = t('files_trashbin', 'Deleted files'); + + FileList._deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/); + + /** + * Convert a file name in the format filename.d12345 to the real file name. + * This will use basename. + * The name will not be changed if it has no ".d12345" suffix. + * @param name file name + * @return converted file name + */ + FileList.getDeletedFileName = function(name) { + name = OC.basename(name); + var match = FileList._deletedRegExp.exec(name); + if (match && match.length > 1) { + name = match[1]; } - }); -}; - -FileList.appName = t('files_trashbin', 'Deleted files'); - -FileList._deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/); - -/** - * Convert a file name in the format filename.d12345 to the real file name. - * This will use basename. - * The name will not be changed if it has no ".d12345" suffix. - * @param name file name - * @return converted file name - */ -FileList.getDeletedFileName = function(name) { - name = OC.basename(name); - var match = FileList._deletedRegExp.exec(name); - if (match && match.length > 1) { - name = match[1]; - } - return name; -}; -var oldSetCurrentDir = FileList.setCurrentDir; -FileList.setCurrentDir = function(targetDir) { - oldSetCurrentDir.apply(this, arguments); - - var baseDir = OC.basename(targetDir); - if (baseDir !== '') { - FileList.setPageTitle(FileList.getDeletedFileName(baseDir)); - } -}; - -FileList.linkTo = function(dir){ - return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); -} - -FileList.updateEmptyContent = function(){ - var $fileList = $('#fileList'); - var exists = $fileList.find('tr:first').exists(); - $('#emptycontent').toggleClass('hidden', exists); - $('#filestable th').toggleClass('hidden', !exists); -} + return name; + }; + + var oldSetCurrentDir = FileList._setCurrentDir; + FileList._setCurrentDir = function(targetDir) { + oldSetCurrentDir.apply(this, arguments); + + var baseDir = OC.basename(targetDir); + if (baseDir !== '') { + FileList.setPageTitle(FileList.getDeletedFileName(baseDir)); + } + }; + + var oldCreateRow = FileList._createRow; + FileList._createRow = function() { + // FIXME: MEGAHACK until we find a better solution + var tr = oldCreateRow.apply(this, arguments); + tr.find('td.filesize').remove(); + return tr; + }; + + FileList._onClickBreadCrumb = function(e) { + var $el = $(e.target).closest('.crumb'), + index = $el.index(), + $targetDir = $el.data('dir'); + // first one is home, let the link makes it default action + if (index !== 0) { + e.preventDefault(); + FileList.changeDirectory($targetDir); + } + }; + + var oldAdd = FileList.add; + FileList.add = function(fileData, options) { + options = options || {}; + var dir = FileList.getCurrentDirectory(); + var dirListing = dir !== '' && dir !== '/'; + // show deleted time as mtime + if (fileData.mtime) { + fileData.mtime = parseInt(fileData.mtime, 10); + } + if (!dirListing) { + fileData.displayName = fileData.name; + fileData.name = fileData.name + '.d' + Math.floor(fileData.mtime / 1000); + } + return oldAdd.call(this, fileData, options); + }; + + FileList.linkTo = function(dir){ + return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); + }; + + FileList.updateEmptyContent = function(){ + var $fileList = $('#fileList'); + var exists = $fileList.find('tr:first').exists(); + $('#emptycontent').toggleClass('hidden', exists); + $('#filestable th').toggleClass('hidden', !exists); + }; +})(); diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 6aade210505e78cca7d1a94cde032d628a71234b..5cd49e19aaacab86488be40b35ccfe60e1bf2ba5 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -8,9 +8,26 @@ * */ -/* global OC, t, FileList, FileActions */ - +/* global OC, t, BreadCrumb, FileActions, FileList, Files */ $(document).ready(function() { + var deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/); + + /** + * Convert a file name in the format filename.d12345 to the real file name. + * This will use basename. + * The name will not be changed if it has no ".d12345" suffix. + * @param name file name + * @return converted file name + */ + function getDeletedFileName(name) { + name = OC.basename(name); + var match = deletedRegExp.exec(name); + if (match && match.length > 1) { + name = match[1]; + } + return name; + } + function removeCallback(result) { if (result.status !== 'success') { OC.dialogs.alert(result.data.message, t('core', 'Error')); @@ -18,13 +35,18 @@ $(document).ready(function() { var files = result.data.success; for (var i = 0; i < files.length; i++) { - FileList.findFileEl(OC.basename(files[i].filename)).remove(); + FileList.remove(OC.basename(files[i].filename), {updateSummary: false}); } FileList.updateFileSummary(); FileList.updateEmptyContent(); enableActions(); } + Files.updateStorageStatistics = function() { + // no op because the trashbin doesn't have + // storage info like free space / used space + }; + if (typeof FileActions !== 'undefined') { FileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/history'), function(filename) { var tr = FileList.findFileEl(filename); @@ -69,7 +91,6 @@ $(document).ready(function() { } procesSelection(); }); - $('.undelete').click('click', function(event) { event.preventDefault(); var allFiles = $('#select_all').is(':checked'); @@ -84,7 +105,7 @@ $(document).ready(function() { }; } else { - files = getSelectedFiles('name'); + files = Files.getSelectedFiles('name'); for (var i = 0; i < files.length; i++) { var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); deleteAction.removeClass('delete-icon').addClass('progress-icon'); @@ -126,7 +147,7 @@ $(document).ready(function() { }; } else { - files = getSelectedFiles('name'); + files = Files.getSelectedFiles('name'); params = { files: JSON.stringify(files), dir: FileList.getCurrentDirectory() @@ -153,7 +174,7 @@ $(document).ready(function() { } FileList.hideMask(); // simply remove all files - FileList.update(''); + FileList.setFiles([]); enableActions(); } else { @@ -186,7 +207,7 @@ $(document).ready(function() { var filename = $(this).parent().parent().attr('data-file'); var tr = FileList.findFileEl(filename); var renaming = tr.data('renaming'); - if(!renaming && !FileList.isLoading(filename)){ + if(!renaming){ if(mime.substr(0, 5) === 'text/'){ //no texteditor for now return; } @@ -198,47 +219,61 @@ $(document).ready(function() { action(filename); } } - - // event handlers for breadcrumb items - $('#controls').delegate('.crumb:not(.home) a', 'click', onClickBreadcrumb); }); - FileActions.actions.dir = { - // only keep 'Open' action for navigation - 'Open': FileActions.actions.dir.Open + /** + * Override crumb URL maker (hacky!) + */ + FileList.breadcrumb.getCrumbUrl = function(part, index) { + if (index === 0) { + return OC.linkTo('files', 'index.php'); + } + return OC.linkTo('files_trashbin', 'index.php')+"?dir=" + encodeURIComponent(part.dir); }; -}); -/** - * @brief get a list of selected files - * @param string property (option) the property of the file requested - * @return array - * - * possible values for property: name, mime, size and type - * if property is set, an array with that property for each file is returnd - * if it's ommited an array of objects with all properties is returned - */ -function getSelectedFiles(property){ - var elements=$('td.filename input:checkbox:checked').parent().parent(); - var files=[]; - elements.each(function(i,element){ - var file={ - name:$(element).attr('data-file'), - timestamp:$(element).attr('data-timestamp'), - type:$(element).attr('data-type') + Files.generatePreviewUrl = function(urlSpec) { + return OC.generateUrl('/apps/files_trashbin/ajax/preview.php?') + $.param(urlSpec); + }; + + Files.getDownloadUrl = function(action, params) { + // no downloads + return '#'; + }; + + Files.getAjaxUrl = function(action, params) { + var q = ''; + if (params) { + q = '?' + OC.buildQueryString(params); + } + return OC.filePath('files_trashbin', 'ajax', action + '.php') + q; + }; + + + /** + * Override crumb making to add "Deleted Files" entry + * and convert files with ".d" extensions to a more + * user friendly name. + */ + var oldMakeCrumbs = BreadCrumb.prototype._makeCrumbs; + BreadCrumb.prototype._makeCrumbs = function() { + var parts = oldMakeCrumbs.apply(this, arguments); + // duplicate first part + parts.unshift(parts[0]); + parts[1] = { + dir: '/', + name: t('files_trashbin', 'Deleted Files') }; - if(property){ - files.push(file[property]); - }else{ - files.push(file); + for (var i = 2; i < parts.length; i++) { + parts[i].name = getDeletedFileName(parts[i].name); } - }); - return files; -} + return parts; + }; -function fileDownloadPath(dir, file) { - return OC.filePath('files_trashbin', '', 'download.php') + '?file='+encodeURIComponent(file); -} + FileActions.actions.dir = { + // only keep 'Open' action for navigation + 'Open': FileActions.actions.dir.Open + }; +}); function enableActions() { $(".action").css("display", "inline"); diff --git a/apps/files_trashbin/l10n/ar.php b/apps/files_trashbin/l10n/ar.php index 68c51d1cc7dd7f80334ac8ad028e8359033bff0a..4084daa127a3c8675ff298d82e93ece09a20988e 100644 --- a/apps/files_trashbin/l10n/ar.php +++ b/apps/files_trashbin/l10n/ar.php @@ -4,6 +4,7 @@ $TRANSLATIONS = array( "Couldn't restore %s" => "تعذّر استرجاع %s ", "Deleted files" => "حذف الملفات", "Error" => "خطأ", +"restored" => "تمت الاستعادة", "Nothing in here. Your trash bin is empty!" => "لا يوجد شيء هنا. سلة المهملات خاليه.", "Name" => "اسم", "Restore" => "استعيد", diff --git a/apps/files_trashbin/l10n/ast.php b/apps/files_trashbin/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..91c122bd4d3ccfda290e53a01696ea4144ad2ee3 --- /dev/null +++ b/apps/files_trashbin/l10n/ast.php @@ -0,0 +1,8 @@ + "Fallu", +"Name" => "Nome", +"Restore" => "Restaurar", +"Delete" => "Desaniciar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_trashbin/l10n/tr.php b/apps/files_trashbin/l10n/tr.php index c1234cdfb0ca79bc0db98753fc64cd02fe67311b..ff4227e38c74a8d2c99b423b7e63e760a0237209 100644 --- a/apps/files_trashbin/l10n/tr.php +++ b/apps/files_trashbin/l10n/tr.php @@ -1,15 +1,15 @@ "%s alıcı olarak silinemedi", -"Couldn't restore %s" => "%s eri yüklenemedi", +"Couldn't restore %s" => "%s geri yüklenemedi", "Deleted files" => "Silinmiş dosyalar", "Error" => "Hata", +"Deleted Files" => "Silinen Dosyalar", "restored" => "geri yüklendi", "Nothing in here. Your trash bin is empty!" => "Burada hiçbir şey yok. Çöp kutunuz tamamen boş!", "Name" => "İsim", "Restore" => "Geri yükle", "Deleted" => "Silindi", -"Delete" => "Sil", -"Deleted Files" => "Silinen Dosyalar" +"Delete" => "Sil" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php index 9c24332a964dd2227ab1dfd9c5d6d640229a8481..e6ca73520a6fe5bb747d7ff06e3c4ea5152e7afe 100644 --- a/apps/files_trashbin/lib/helper.php +++ b/apps/files_trashbin/lib/helper.php @@ -27,6 +27,10 @@ class Helper if ($dirContent === false) { return $result; } + + list($storage, $internalPath) = $view->resolvePath($dir); + $absoluteDir = $view->getAbsolutePath($dir); + if (is_resource($dirContent)) { while (($entryName = readdir($dirContent)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { @@ -40,76 +44,41 @@ class Helper $parts = explode('/', ltrim($dir, '/')); $timestamp = substr(pathinfo($parts[0], PATHINFO_EXTENSION), 1); } - $result[] = array( - 'id' => $id, - 'timestamp' => $timestamp, - 'mime' => \OC_Helper::getFileNameMimeType($id), + $i = array( + 'name' => $id, + 'mtime' => $timestamp, + 'mimetype' => \OC_Helper::getFileNameMimeType($id), 'type' => $view->is_dir($dir . '/' . $entryName) ? 'dir' : 'file', - 'location' => $dir, + 'directory' => ($dir === '/') ? '' : $dir, ); + $result[] = new FileInfo($absoluteDir . '/' . $i['name'], $storage, $internalPath . '/' . $i['name'], $i); } } closedir($dirContent); } - $files = array(); - $id = 0; - list($storage, $internalPath) = $view->resolvePath($dir); - $absoluteDir = $view->getAbsolutePath($dir); - foreach ($result as $r) { - $i = array(); - $i['id'] = $id++; - $i['name'] = $r['id']; - $i['date'] = \OCP\Util::formatDate($r['timestamp']); - $i['timestamp'] = $r['timestamp']; - $i['etag'] = $r['timestamp']; // add fake etag, it is only needed to identify the preview image - $i['mimetype'] = $r['mime']; - $i['type'] = $r['type']; - if ($i['type'] === 'file') { - $fileinfo = pathinfo($r['id']); - $i['basename'] = $fileinfo['filename']; - $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; - } - $i['directory'] = $r['location']; - if ($i['directory'] === '/') { - $i['directory'] = ''; - } - $i['permissions'] = \OCP\PERMISSION_READ; - if (\OCP\App::isEnabled('files_encryption')) { - $i['isPreviewAvailable'] = false; - } else { - $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($r['mime']); - } - $i['icon'] = \OCA\Files\Helper::determineIcon($i); - $files[] = new FileInfo($absoluteDir . '/' . $i['name'], $storage, $internalPath . '/' . $i['name'], $i); - } - - usort($files, array('\OCA\Files\Helper', 'fileCmp')); + usort($result, array('\OCA\Files\Helper', 'fileCmp')); - return $files; + return $result; } /** - * Splits the given path into a breadcrumb structure. - * @param string $dir path to process - * @return array where each entry is a hash of the absolute - * directory path and its name + * Format file infos for JSON + * @param \OCP\Files\FileInfo[] $fileInfos file infos */ - public static function makeBreadcrumb($dir){ - // Make breadcrumb - $pathtohere = ''; - $breadcrumb = array(); - foreach (explode('/', $dir) as $i) { - if ($i !== '') { - if ( preg_match('/^(.+)\.d[0-9]+$/', $i, $match) ) { - $name = $match[1]; - } else { - $name = $i; - } - $pathtohere .= '/' . $i; - $breadcrumb[] = array('dir' => $pathtohere, 'name' => $name); + public static function formatFileInfos($fileInfos) { + $files = array(); + $id = 0; + foreach ($fileInfos as $i) { + $entry = \OCA\Files\Helper::formatFileInfo($i); + $entry['id'] = $id++; + $entry['etag'] = $entry['mtime']; // add fake etag, it is only needed to identify the preview image + $entry['permissions'] = \OCP\PERMISSION_READ; + if (\OCP\App::isEnabled('files_encryption')) { + $entry['isPreviewAvailable'] = false; } + $files[] = $entry; } - return $breadcrumb; + return $files; } } diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index f9264d4352cca017004e6a3021f304bd5feb5dde..b6c61c9b1c3ea136b2727fda463d8e385a505668 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -1,12 +1,11 @@
- -
+
-
class="hidden">t('Nothing in here. Your trash bin is empty!'))?>
+ - + @@ -40,6 +39,5 @@
-
diff --git a/apps/files_trashbin/templates/part.breadcrumb.php b/apps/files_trashbin/templates/part.breadcrumb.php deleted file mode 100644 index fdf78c190d0bbe1ed03096dba4768b8203723645..0000000000000000000000000000000000000000 --- a/apps/files_trashbin/templates/part.breadcrumb.php +++ /dev/null @@ -1,19 +0,0 @@ -
- - - - -
svg" - data-dir=''> - -
-200) $relative_date_color = 200; - $name = \OCP\Util::encodePath($file['name']); - $directory = \OCP\Util::encodePath($file['directory']); ?> - ' - - id="" - data-file="" - data-timestamp='' - data-dirlisting=1 - - id="" - data-file="" - data-timestamp='' - data-dirlisting=0 - > - - - - - style="background-image:url()" - - - style="background-image:url()" - - style="background-image:url()" - - - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ownCloud supports simple version control for files. The versioning app expires old versions automatically to make sure that - the user doesn't run out of space. Following pattern is used to delete + the user doesn't run out of space. The following pattern is used to delete old versions: For the first 10 seconds ownCloud keeps one version every 2 seconds; For the first hour ownCloud keeps one version every minute; diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js index 4adf14745de06c54fd495e63568ebaa89e882cc7..b452bc25b13d4c3c9bf5dd6d5afcdea78d8fb96d 100644 --- a/apps/files_versions/js/versions.js +++ b/apps/files_versions/js/versions.js @@ -11,7 +11,7 @@ $(document).ready(function(){ // Add versions button to 'files/index.php' FileActions.register( 'file' - , t('files_versions', 'Versions') + , 'Versions' , OC.PERMISSION_UPDATE , function() { // Specify icon for hitory button @@ -36,6 +36,7 @@ $(document).ready(function(){ createVersionsDropdown(filename, file); } } + , t('files_versions', 'Versions') ); } diff --git a/apps/files_versions/l10n/ast.php b/apps/files_versions/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..4869d70b54d5d09cb4958d2fe5b78da4cef1d6e4 --- /dev/null +++ b/apps/files_versions/l10n/ast.php @@ -0,0 +1,8 @@ + "Versiones", +"More versions..." => "Más versiones...", +"No other versions available" => "Nun hai otres versiones disponibles", +"Restore" => "Restaurar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/appinfo/info.xml b/apps/user_ldap/appinfo/info.xml index 9cc908e8522220f1c045d475e511d45fde81a51b..e4a4375a737fed5eaf489e7e9013ad9e6d8ab96f 100644 --- a/apps/user_ldap/appinfo/info.xml +++ b/apps/user_ldap/appinfo/info.xml @@ -2,8 +2,8 @@ user_ldap LDAP user and group backend - Authenticate users and groups by LDAP respectively Active - Directory. + Authenticate users and groups through LDAP, such as OpenLDAP + or Active Directory. This app is not compatible with the WebDAV user backend. diff --git a/apps/user_ldap/group_ldap.php b/apps/user_ldap/group_ldap.php index cef9ca3c4cff1f9258b121a9a42c802045b37049..40d9dec14101d4290c102452074421281d65477c 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -276,6 +276,84 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return $groupUsers; } + /** + * @brief returns the number of users in a group, who match the search term + * @param string the internal group name + * @param string optional, a search string + * @returns int | bool + */ + public function countUsersInGroup($gid, $search = '') { + $cachekey = 'countUsersInGroup-'.$gid.'-'.$search; + if(!$this->enabled || !$this->groupExists($gid)) { + return false; + } + $groupUsers = $this->access->connection->getFromCache($cachekey); + if(!is_null($groupUsers)) { + return $groupUsers; + } + + $groupDN = $this->access->groupname2dn($gid); + if(!$groupDN) { + // group couldn't be found, return empty resultset + $this->access->connection->writeToCache($cachekey, false); + return false; + } + + $members = array_keys($this->_groupMembers($groupDN)); + if(!$members) { + //in case users could not be retrieved, return empty resultset + $this->access->connection->writeToCache($cachekey, false); + return false; + } + + if(empty($search)) { + $groupUsers = count($members); + $this->access->connection->writeToCache($cachekey, $groupUsers); + return $groupUsers; + } + $isMemberUid = + (strtolower($this->access->connection->ldapGroupMemberAssocAttr) + === 'memberuid'); + + //we need to apply the search filter + //alternatives that need to be checked: + //a) get all users by search filter and array_intersect them + //b) a, but only when less than 1k 10k ?k users like it is + //c) put all DNs|uids in a LDAP filter, combine with the search string + // and let it count. + //For now this is not important, because the only use of this method + //does not supply a search string + $groupUsers = array(); + foreach($members as $member) { + if($isMemberUid) { + //we got uids, need to get their DNs to 'tranlsate' them to usernames + $filter = $this->access->combineFilterWithAnd(array( + \OCP\Util::mb_str_replace('%uid', $member, + $this->access->connection->ldapLoginFilter, 'UTF-8'), + $this->access->getFilterPartForUserSearch($search) + )); + $ldap_users = $this->access->fetchListOfUsers($filter, 'dn'); + if(count($ldap_users) < 1) { + continue; + } + $groupUsers[] = $this->access->dn2username($ldap_users[0]); + } else { + //we need to apply the search filter now + if(!$this->access->readAttribute($member, + $this->access->connection->ldapUserDisplayName, + $this->access->getFilterPartForUserSearch($search))) { + continue; + } + // dn2username will also check if the users belong to the allowed base + if($ocname = $this->access->dn2username($member)) { + $groupUsers[] = $ocname; + } + } + } + + return count($groupUsers); + } + /** * @brief get a list of all display names in a group * @returns array with display names (value) and user ids(key) @@ -299,9 +377,9 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { * @brief get a list of all groups * @returns array with group names * - * Returns a list with all groups + * Returns a list with all groups (used by getGroups) */ - public function getGroups($search = '', $limit = -1, $offset = 0) { + protected function getGroupsChunk($search = '', $limit = -1, $offset = 0) { if(!$this->enabled) { return array(); } @@ -334,6 +412,48 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return $ldap_groups; } + /** + * @brief get a list of all groups using a paged search + * @returns array with group names + * + * Returns a list with all groups + * Uses a paged search if available to override a + * server side search limit. + * (active directory has a limit of 1000 by default) + */ + public function getGroups($search = '', $limit = -1, $offset = 0) { + if(!$this->enabled) { + return array(); + } + $pagingsize = $this->access->connection->ldapPagingSize; + if ((! $this->access->connection->hasPagedResultSupport) + || empty($pagingsize)) { + return $this->getGroupsChunk($search, $limit, $offset); + } + $maxGroups = 100000; // limit max results (just for safety reasons) + if ($limit > -1) { + $overallLimit = min($limit, $maxGroups); + } else { + $overallLimit = $maxGroups; + } + $chunkOffset = $offset; + $allGroups = array(); + while ($chunkOffset < $overallLimit) { + $chunkLimit = min($pagingsize, $overallLimit - $chunkOffset); + $ldapGroups = $this->getGroupsChunk($search, $chunkLimit, $chunkOffset); + $nread = count($ldapGroups); + \OCP\Util::writeLog('user_ldap', 'getGroups('.$search.'): read '.$nread.' at offset '.$chunkOffset.' (limit: '.$chunkLimit.')', \OCP\Util::DEBUG); + if ($nread) { + $allGroups = array_merge($allGroups, $ldapGroups); + $chunkOffset += $nread; + } + if ($nread < $chunkLimit) { + break; + } + } + return $allGroups; + } + public function groupMatchesFilter($group) { return (strripos($group, $this->groupSearch) !== false); } @@ -376,6 +496,9 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { * compared with OC_USER_BACKEND_CREATE_USER etc. */ public function implementsActions($actions) { - return (bool)(OC_GROUP_BACKEND_GET_DISPLAYNAME & $actions); + return (bool)(( + OC_GROUP_BACKEND_GET_DISPLAYNAME + | OC_GROUP_BACKEND_COUNT_USERS + ) & $actions); } } diff --git a/apps/user_ldap/group_proxy.php b/apps/user_ldap/group_proxy.php index 4404bd7fe3a0567f4deba34e1d1591ea7f090ed0..c00097362399bec634a33d4bb2dd4e723ba0d1ce 100644 --- a/apps/user_ldap/group_proxy.php +++ b/apps/user_ldap/group_proxy.php @@ -144,6 +144,17 @@ class Group_Proxy extends lib\Proxy implements \OCP\GroupInterface { return $users; } + /** + * @brief returns the number of users in a group, who match the search term + * @param string the internal group name + * @param string optional, a search string + * @returns int | bool + */ + public function countUsersInGroup($gid, $search = '') { + return $this->handleRequest( + $gid, 'countUsersInGroup', array($gid, $search)); + } + /** * @brief get a list of all display names in a group * @returns array with display names (value) and user ids(key) diff --git a/apps/user_ldap/l10n/ast.php b/apps/user_ldap/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..2c0228800190642a14608fdcdf2b8bf83f45f12f --- /dev/null +++ b/apps/user_ldap/l10n/ast.php @@ -0,0 +1,11 @@ + "Falló'l borráu", +"Error" => "Fallu", +"_%s group found_::_%s groups found_" => array("",""), +"_%s user found_::_%s users found_" => array("",""), +"Save" => "Guardar", +"Password" => "Contraseña", +"Continue" => "Continuar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/az.php b/apps/user_ldap/l10n/az.php index bba52d53a1ac80dd76da8680c20f85865d5a99b2..3a1e002311cd9c1851bda1b96f71bc4d3e3e047b 100644 --- a/apps/user_ldap/l10n/az.php +++ b/apps/user_ldap/l10n/az.php @@ -1,6 +1,6 @@ array(""), -"_%s user found_::_%s users found_" => array("") +"_%s group found_::_%s groups found_" => array("",""), +"_%s user found_::_%s users found_" => array("","") ); -$PLURAL_FORMS = "nplurals=1; plural=0;"; +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/bn_BD.php b/apps/user_ldap/l10n/bn_BD.php index 0b43a27df940d9ecd1f4efee7bcb5758b2e3984c..90f7b572a952c71e5c0476d57e6a9b14ae23d623 100644 --- a/apps/user_ldap/l10n/bn_BD.php +++ b/apps/user_ldap/l10n/bn_BD.php @@ -13,7 +13,6 @@ $TRANSLATIONS = array( "Password" => "কূটশব্দ", "For anonymous access, leave DN and Password empty." => "অজ্ঞাতকুলশীল অধিগমনের জন্য DN এবং কূটশব্দটি ফাঁকা রাখুন।", "You can specify Base DN for users and groups in the Advanced tab" => "সুচারু ট্যঅবে গিয়ে আপনি ব্যবহারকারি এবং গোষ্ঠীসমূহের জন্য ভিত্তি DN নির্ধারণ করতে পারেন।", -"Case insensitve LDAP server (Windows)" => "বর্ণ অসংবেদী LDAP সার্ভার (উইন্ডোজ)", "Turn off SSL certificate validation." => "SSL সনদপত্র যাচাইকরণ বন্ধ রাক।", "in seconds. A change empties the cache." => "সেকেন্ডে। কোন পরিবর্তন ক্যাসে খালি করবে।", "User Display Name Field" => "ব্যবহারকারীর প্রদর্শিতব্য নামের ক্ষেত্র", diff --git a/apps/user_ldap/l10n/ca.php b/apps/user_ldap/l10n/ca.php index 940c6ea8b6608735044f16b0acffab1749e9ace7..98b1cf7464037447748b134aa75f960cce0ab684 100644 --- a/apps/user_ldap/l10n/ca.php +++ b/apps/user_ldap/l10n/ca.php @@ -70,7 +70,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Port de la còpia de seguretat (rèplica)", "Disable Main Server" => "Desactiva el servidor principal", "Only connect to the replica server." => "Connecta només al servidor rèplica.", -"Case insensitve LDAP server (Windows)" => "Servidor LDAP sense distinció entre majúscules i minúscules (Windows)", "Turn off SSL certificate validation." => "Desactiva la validació de certificat SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "No es recomana, useu-ho només com a prova! Importeu el certificat SSL del servidor LDAP al servidor %s només si la connexió funciona amb aquesta opció.", "Cache Time-To-Live" => "Memòria de cau Time-To-Live", diff --git a/apps/user_ldap/l10n/cs_CZ.php b/apps/user_ldap/l10n/cs_CZ.php index 536834ee8b54053187589299576725a040b10cfc..d4039e9ef10121da72426d58a44b4b85731318cf 100644 --- a/apps/user_ldap/l10n/cs_CZ.php +++ b/apps/user_ldap/l10n/cs_CZ.php @@ -70,7 +70,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Záložní (kopie) port", "Disable Main Server" => "Zakázat hlavní server", "Only connect to the replica server." => "Připojit jen k záložnímu serveru.", -"Case insensitve LDAP server (Windows)" => "LDAP server nerozlišující velikost znaků (Windows)", "Turn off SSL certificate validation." => "Vypnout ověřování SSL certifikátu.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Nedoporučuje se, určeno pouze k testovacímu použití. Pokud spojení funguje jen s touto volbou, importujte SSL certifikát vašeho LDAP serveru na server %s.", "Cache Time-To-Live" => "TTL vyrovnávací paměti", diff --git a/apps/user_ldap/l10n/da.php b/apps/user_ldap/l10n/da.php index e375598c9bd1cd2e8b73dca48a72912d60b7f98d..8264a18116c9292427e8189f9e8653379ab2998b 100644 --- a/apps/user_ldap/l10n/da.php +++ b/apps/user_ldap/l10n/da.php @@ -35,7 +35,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Backup (Replika) Port", "Disable Main Server" => "Deaktiver Hovedserver", "Only connect to the replica server." => "Forbind kun til replika serveren.", -"Case insensitve LDAP server (Windows)" => "Ikke versalfølsom LDAP server (Windows)", "Turn off SSL certificate validation." => "Deaktiver SSL certifikat validering", "Cache Time-To-Live" => "Cache Time-To-Live", "User Display Name Field" => "User Display Name Field", diff --git a/apps/user_ldap/l10n/de.php b/apps/user_ldap/l10n/de.php index 8dad9b34539f48c2e573b1403d008093e2a63993..43336520739fd3d6db89f89bfbd459902a1799e4 100644 --- a/apps/user_ldap/l10n/de.php +++ b/apps/user_ldap/l10n/de.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Backup Port", "Disable Main Server" => "Hauptserver deaktivieren", "Only connect to the replica server." => "Nur zum Replikat-Server verbinden.", -"Case insensitve LDAP server (Windows)" => "LDAP-Server (Windows: Groß- und Kleinschreibung bleibt unbeachtet)", +"Case insensitive LDAP server (Windows)" => "LDAP-Server (Windows - Groß- und Kleinschreibung bleibt unbeachtet)", "Turn off SSL certificate validation." => "Schalte die SSL-Zertifikatsprüfung aus.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Nur für Testzwecke geeignet, sollte Standardmäßig nicht verwendet werden. Falls die Verbindung nur mit dieser Option funktioniert, importiere das SSL-Zertifikat des LDAP-Servers in deinen %s Server.", "Cache Time-To-Live" => "Speichere Time-To-Live zwischen", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Assoziation zwischen Gruppe und Benutzer", "Nested Groups" => "Eingebundene Gruppen", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Wenn aktiviert, werden Gruppen, die Gruppen enthalten, unterstützt. (Funktioniert nur, wenn das Merkmal des Gruppenmitgliedes den Domain-Namen enthält.)", +"Paging chunksize" => "Seitenstücke (Paging chunksize)", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Die Größe der Seitenstücke (Chunksize) wird für seitenbezogene LDAP-Suchen verwendet die sehr viele Ergebnisse z.B. Nutzer- und Gruppenaufzählungen liefern. (Die Einstellung 0 deaktiviert das seitenbezogene LDAP-Suchen in diesen Situationen)", "Special Attributes" => "Spezielle Eigenschaften", "Quota Field" => "Kontingent Feld", "Quota Default" => "Standard Kontingent", diff --git a/apps/user_ldap/l10n/de_CH.php b/apps/user_ldap/l10n/de_CH.php index 5f8e2907f0747fcd9f914d384a64f00e57ce6137..f60d425a2e6adb04dbd3af4a96913ff116b2a8fb 100644 --- a/apps/user_ldap/l10n/de_CH.php +++ b/apps/user_ldap/l10n/de_CH.php @@ -42,7 +42,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Backup Port", "Disable Main Server" => "Hauptserver deaktivieren", "Only connect to the replica server." => "Nur zum Replikat-Server verbinden.", -"Case insensitve LDAP server (Windows)" => "LDAP-Server (Windows: Gross- und Kleinschreibung bleibt unbeachtet)", "Turn off SSL certificate validation." => "Schalten Sie die SSL-Zertifikatsprüfung aus.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Nur für Testzwecke geeignet, sollte Standardmäßig nicht verwendet werden. Falls die Verbindung nur mit dieser Option funktioniert, importieren Sie das SSL-Zertifikat des LDAP-Servers in Ihren %s Server.", "Cache Time-To-Live" => "Speichere Time-To-Live zwischen", diff --git a/apps/user_ldap/l10n/de_DE.php b/apps/user_ldap/l10n/de_DE.php index 6e6e29ea3db0cb18c1383199886410982622400c..21c149d1a1d243ca47bc88ce6a50507abc293cf8 100644 --- a/apps/user_ldap/l10n/de_DE.php +++ b/apps/user_ldap/l10n/de_DE.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Backup Port", "Disable Main Server" => "Hauptserver deaktivieren", "Only connect to the replica server." => "Nur zum Replikat-Server verbinden.", -"Case insensitve LDAP server (Windows)" => "LDAP-Server (Windows: Groß- und Kleinschreibung bleibt unbeachtet)", +"Case insensitive LDAP server (Windows)" => "LDAP-Server (Windows: Groß- und Kleinschreibung bleibt unbeachtet)", "Turn off SSL certificate validation." => "Schalten Sie die SSL-Zertifikatsprüfung aus.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Nur für Testzwecke geeignet, sollte Standardmäßig nicht verwendet werden. Falls die Verbindung nur mit dieser Option funktioniert, importieren Sie das SSL-Zertifikat des LDAP-Servers in Ihren %s Server.", "Cache Time-To-Live" => "Speichere Time-To-Live zwischen", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Assoziation zwischen Gruppe und Benutzer", "Nested Groups" => "Eingebundene Gruppen", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Wenn aktiviert, werden Gruppen, die Gruppen enthalten, unterstützt. (Funktioniert nur, wenn das Merkmal des Gruppenmitgliedes den Domain-Namen enthält.)", +"Paging chunksize" => "Seitenstücke (Paging chunksize)", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Die Größe der Seitenstücke (Chunksize) wird für seitenbezogene LDAP-Suchen verwendet die sehr viele Ergebnisse z.B. Nutzer- und Gruppenaufzählungen liefern. (Die Einstellung 0 deaktiviert das seitenbezogene LDAP-Suchen in diesen Situationen)", "Special Attributes" => "Spezielle Eigenschaften", "Quota Field" => "Kontingent-Feld", "Quota Default" => "Standard-Kontingent", diff --git a/apps/user_ldap/l10n/el.php b/apps/user_ldap/l10n/el.php index 1e9759119537900c45db8df198b432a4243531d9..cfc5286a4084bbe498f91376d62aa2a0db1ba06b 100644 --- a/apps/user_ldap/l10n/el.php +++ b/apps/user_ldap/l10n/el.php @@ -33,12 +33,14 @@ $TRANSLATIONS = array( "Save" => "Αποθήκευση", "Test Configuration" => "Δοκιμαστικες ρυθμισεις", "Help" => "Βοήθεια", +"Groups meeting these criteria are available in %s:" => "Οι ομάδες που πληρούν τα κριτήρια είναι διαθέσιμες σε %s:", "only those object classes:" => "μόνο αυτές οι κλάσεις αντικειμένων:", "only from those groups:" => "μόνο από αυτές τις ομάδες:", "Edit raw filter instead" => "Επεξεργασία πρωτογενούς φίλτρου αντί αυτού", "Raw LDAP filter" => "Πρωτογενές φίλτρο ", "The filter specifies which LDAP groups shall have access to the %s instance." => "Το φίλτρο καθορίζει ποιες ομάδες LDAP θα έχουν πρόσβαση στην εγκατάσταση %s.", "groups found" => "ομάδες βρέθηκαν", +"Users login with this attribute:" => "Οι χρήστες εισέρχονται με αυτό το χαρακτηριστικό:", "LDAP Username:" => "Όνομα χρήστη LDAP:", "LDAP Email Address:" => "Διεύθυνση ηλ. ταχυδρομείου LDAP:", "Other Attributes:" => "Άλλες Ιδιότητες:", @@ -53,6 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Για ανώνυμη πρόσβαση, αφήστε κενά τα πεδία DN και Pasword.", "One Base DN per line" => "Ένα DN Βάσης ανά γραμμή ", "You can specify Base DN for users and groups in the Advanced tab" => "Μπορείτε να καθορίσετε το Base DN για χρήστες και ομάδες από την καρτέλα Προηγμένες ρυθμίσεις", +"Limit %s access to users meeting these criteria:" => "Περιορισμός της πρόσβασης %s σε χρήστες που πληρούν τα κριτήρια:", "The filter specifies which LDAP users shall have access to the %s instance." => "Το φίλτρο καθορίζει ποιοι χρήστες LDAP θα έχουν πρόσβαση στην εγκατάσταση %s.", "users found" => "χρήστες βρέθηκαν", "Back" => "Επιστροφή", @@ -67,7 +70,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Δημιουργία αντιγράφων ασφαλείας (Replica) Υποδοχη", "Disable Main Server" => "Απενεργοποιηση του κεντρικου διακομιστη", "Only connect to the replica server." => "Σύνδεση μόνο με το διακομιστή-αντίγραφο.", -"Case insensitve LDAP server (Windows)" => "LDAP server (Windows) με διάκριση πεζών-ΚΕΦΑΛΑΙΩΝ", "Turn off SSL certificate validation." => "Απενεργοποίηση επικύρωσης πιστοποιητικού SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Δεν προτείνεται, χρησιμοποιείστε το μόνο για δοκιμές! Εάν η σύνδεση λειτουργεί μόνο με αυτή την επιλογή, εισάγετε το πιστοποιητικό SSL του διακομιστή LDAP στο %s διακομιστή σας.", "Cache Time-To-Live" => "Cache Time-To-Live", @@ -85,6 +87,7 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Μια ομαδικη Βάση DN ανά γραμμή", "Group Search Attributes" => "Ομάδα Χαρακτηριστικων Αναζήτηση", "Group-Member association" => "Group-Member association", +"Nested Groups" => "Φωλιασμένες ομάδες", "Special Attributes" => "Ειδικά Χαρακτηριστικά ", "Quota Field" => "Ποσοσταση πεδιου", "Quota Default" => "Προκαθισμενο πεδιο", diff --git a/apps/user_ldap/l10n/en_GB.php b/apps/user_ldap/l10n/en_GB.php index 4421a8035ca4f24c41c55cbc9055b802864e28e6..6dfc3e53f0c1e0192cae047bb4a6611aee049751 100644 --- a/apps/user_ldap/l10n/en_GB.php +++ b/apps/user_ldap/l10n/en_GB.php @@ -70,7 +70,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Backup (Replica) Port", "Disable Main Server" => "Disable Main Server", "Only connect to the replica server." => "Only connect to the replica server.", -"Case insensitve LDAP server (Windows)" => "Case insensitve LDAP server (Windows)", "Turn off SSL certificate validation." => "Turn off SSL certificate validation.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server.", "Cache Time-To-Live" => "Cache Time-To-Live", @@ -90,6 +89,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Group-Member association", "Nested Groups" => "Nested Groups", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)", +"Paging chunksize" => "Paging chunksize", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)", "Special Attributes" => "Special Attributes", "Quota Field" => "Quota Field", "Quota Default" => "Quota Default", diff --git a/apps/user_ldap/l10n/eo.php b/apps/user_ldap/l10n/eo.php index 0cae524bcc1649c4fb8cb0123857d412cd216154..74928899c8a39623cab319eec90ac84f67d0ed92 100644 --- a/apps/user_ldap/l10n/eo.php +++ b/apps/user_ldap/l10n/eo.php @@ -35,7 +35,6 @@ $TRANSLATIONS = array( "Back" => "Antaŭen", "Connection Settings" => "Agordo de konekto", "Disable Main Server" => "Malkapabligi la ĉefan servilon", -"Case insensitve LDAP server (Windows)" => "LDAP-servilo blinda je litergrandeco (Vindozo)", "Turn off SSL certificate validation." => "Malkapabligi validkontrolon de SSL-atestiloj.", "Cache Time-To-Live" => "Vivotempo de la kaŝmemoro", "in seconds. A change empties the cache." => "sekunde. Ajna ŝanĝo malplenigas la kaŝmemoron.", diff --git a/apps/user_ldap/l10n/es.php b/apps/user_ldap/l10n/es.php index 1821aa8d446a84b2f7f9ad17a490a51ae73f31bc..2c294aff785581392acac94ae378f0b0de0e7005 100644 --- a/apps/user_ldap/l10n/es.php +++ b/apps/user_ldap/l10n/es.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Puerto para copias de seguridad (Replica)", "Disable Main Server" => "Deshabilitar servidor principal", "Only connect to the replica server." => "Conectar sólo con el servidor de réplica.", -"Case insensitve LDAP server (Windows)" => "Servidor de LDAP no sensible a mayúsculas/minúsculas (Windows)", +"Case insensitive LDAP server (Windows)" => "Servidor de LDAP insensible a mayúsculas/minúsculas (Windows)", "Turn off SSL certificate validation." => "Apagar la validación por certificado SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "No se recomienda, ¡utilízalo únicamente para pruebas! Si la conexión únicamente funciona con esta opción, importa el certificado SSL del servidor LDAP en tu servidor %s.", "Cache Time-To-Live" => "Cache TTL", diff --git a/apps/user_ldap/l10n/es_AR.php b/apps/user_ldap/l10n/es_AR.php index 6323fe0c4adefc3b2f3b7e08e34e1ded523f85f0..877141bcdc88fd1e89bd287a7d3a7ad40fd808e8 100644 --- a/apps/user_ldap/l10n/es_AR.php +++ b/apps/user_ldap/l10n/es_AR.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Puerto para copia de seguridad (réplica)", "Disable Main Server" => "Deshabilitar el Servidor Principal", "Only connect to the replica server." => "Conectarse únicamente al servidor de réplica.", -"Case insensitve LDAP server (Windows)" => "Servidor de LDAP sensible a mayúsculas/minúsculas (Windows)", "Turn off SSL certificate validation." => "Desactivar la validación por certificado SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "No es recomendado, ¡Usalo solamente para pruebas! Si la conexión únicamente funciona con esta opción, importá el certificado SSL del servidor LDAP en tu servidor %s.", "Cache Time-To-Live" => "Tiempo de vida del caché", diff --git a/apps/user_ldap/l10n/es_MX.php b/apps/user_ldap/l10n/es_MX.php index 09c99209a5578f359210578b477fd9a190d00dd9..bb4c3700ec56d9a374dc11e5e391740cddef7fd7 100644 --- a/apps/user_ldap/l10n/es_MX.php +++ b/apps/user_ldap/l10n/es_MX.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Puerto para copias de seguridad (Replica)", "Disable Main Server" => "Deshabilitar servidor principal", "Only connect to the replica server." => "Conectar sólo con el servidor de réplica.", -"Case insensitve LDAP server (Windows)" => "Servidor de LDAP no sensible a mayúsculas/minúsculas (Windows)", "Turn off SSL certificate validation." => "Apagar la validación por certificado SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "No se recomienda, ¡utilízalo únicamente para pruebas! Si la conexión únicamente funciona con esta opción, importa el certificado SSL del servidor LDAP en tu servidor %s.", "Cache Time-To-Live" => "Cache TTL", diff --git a/apps/user_ldap/l10n/et_EE.php b/apps/user_ldap/l10n/et_EE.php index 090accceda0409b9728324fec3cace02c7222691..f52449bda8be8d62c07ba45e4877c040990a290d 100644 --- a/apps/user_ldap/l10n/et_EE.php +++ b/apps/user_ldap/l10n/et_EE.php @@ -33,12 +33,14 @@ $TRANSLATIONS = array( "Save" => "Salvesta", "Test Configuration" => "Testi seadistust", "Help" => "Abiinfo", +"Groups meeting these criteria are available in %s:" => "Kriteeriumiga sobivad grupid on saadaval %s:", "only those object classes:" => "ainult need objektiklassid:", "only from those groups:" => "ainult nendest gruppidest:", "Edit raw filter instead" => "Selle asemel muuda filtrit", "Raw LDAP filter" => "LDAP filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "Filter määrab millised LDAP grupid saavad ligipääsu sellele %s instantsile.", "groups found" => "gruppi leitud", +"Users login with this attribute:" => "Logimiseks kasutatkse atribuuti: ", "LDAP Username:" => "LDAP kasutajanimi:", "LDAP Email Address:" => "LDAP e-posti aadress:", "Other Attributes:" => "Muud atribuudid:", @@ -53,6 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Anonüümseks ligipääsuks jäta DN ja parool tühjaks.", "One Base DN per line" => "Üks baas-DN rea kohta", "You can specify Base DN for users and groups in the Advanced tab" => "Sa saad kasutajate ja gruppide baas DN-i määrata lisavalikute vahekaardilt", +"Limit %s access to users meeting these criteria:" => "Piira %s liigpääs kriteeriumiga sobivatele kasutajatele:", "The filter specifies which LDAP users shall have access to the %s instance." => "Filter määrab millised LDAP kasutajad pääsevad ligi %s instantsile.", "users found" => "kasutajat leitud", "Back" => "Tagasi", @@ -67,7 +70,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Varuserveri (replika) port", "Disable Main Server" => "Ära kasuta peaserverit", "Only connect to the replica server." => "Ühendu ainult replitseeriva serveriga.", -"Case insensitve LDAP server (Windows)" => "Mittetõstutundlik LDAP server (Windows)", "Turn off SSL certificate validation." => "Lülita SSL sertifikaadi kontrollimine välja.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Pole soovitatav, kasuta seda ainult testimiseks! Kui ühendus toimib ainult selle valikuga, siis impordi LDAP serveri SSL sertifikaat oma %s serverisse.", "Cache Time-To-Live" => "Puhvri iga", @@ -85,6 +87,8 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Üks grupi baas-DN rea kohta", "Group Search Attributes" => "Grupi otsingu atribuudid", "Group-Member association" => "Grupiliikme seotus", +"Nested Groups" => "Sisegrupp", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Sisse lülitamisel on toetatakse gruppe sisaldavad gruppe. (Toimib, kui grupi liikme atribuut sisaldab DN-e.)", "Special Attributes" => "Spetsiifilised atribuudid", "Quota Field" => "Mahupiirangu atribuut", "Quota Default" => "Vaikimisi mahupiirang", diff --git a/apps/user_ldap/l10n/eu.php b/apps/user_ldap/l10n/eu.php index a7bd52e50acadf36101cabd8a29557353be40dc8..c19cb034ad0c3ab0986eca900309dedd8dfd7681 100644 --- a/apps/user_ldap/l10n/eu.php +++ b/apps/user_ldap/l10n/eu.php @@ -61,7 +61,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Babeskopia (Replica) Ataka", "Disable Main Server" => "Desgaitu Zerbitzari Nagusia", "Only connect to the replica server." => "Konektatu bakarrik erreplika zerbitzarira", -"Case insensitve LDAP server (Windows)" => "Maiuskulak eta minuskulak ezberditzen ez dituen LDAP zerbitzaria (windows)", "Turn off SSL certificate validation." => "Ezgaitu SSL ziurtagirien egiaztapena.", "Cache Time-To-Live" => "Katxearen Bizi-Iraupena", "in seconds. A change empties the cache." => "segundutan. Aldaketak katxea husten du.", diff --git a/apps/user_ldap/l10n/fa.php b/apps/user_ldap/l10n/fa.php index 688a6ee0d42b2958a1dfe3fc81499c810be931ae..62a949f88bd58211b6e82b3a6146bf1b3eb3747a 100644 --- a/apps/user_ldap/l10n/fa.php +++ b/apps/user_ldap/l10n/fa.php @@ -34,7 +34,6 @@ $TRANSLATIONS = array( "Backup (Replica) Host" => "پشتیبان گیری (بدل) میزبان", "Backup (Replica) Port" => "پشتیبان گیری (بدل) پورت", "Disable Main Server" => "غیر فعال کردن سرور اصلی", -"Case insensitve LDAP server (Windows)" => "غیر حساس به بزرگی و کوچکی حروف LDAP سرور (ویندوز)", "Turn off SSL certificate validation." => "غیرفعال کردن اعتبار گواهی نامه SSL .", "Directory Settings" => "تنظیمات پوشه", "User Display Name Field" => "فیلد نام کاربر", diff --git a/apps/user_ldap/l10n/fi_FI.php b/apps/user_ldap/l10n/fi_FI.php index ac1dfcc5ab8ca9d3f6d342a0368cbd0212d17abb..552fd9f923bbf63906083533d0bcf7bd40167651 100644 --- a/apps/user_ldap/l10n/fi_FI.php +++ b/apps/user_ldap/l10n/fi_FI.php @@ -25,7 +25,6 @@ $TRANSLATIONS = array( "Continue" => "Jatka", "Connection Settings" => "Yhteysasetukset", "Disable Main Server" => "Poista pääpalvelin käytöstä", -"Case insensitve LDAP server (Windows)" => "Kirjainkoosta piittamaton LDAP-palvelin (Windows)", "Turn off SSL certificate validation." => "Poista käytöstä SSL-varmenteen vahvistus", "in seconds. A change empties the cache." => "sekunneissa. Muutos tyhjentää välimuistin.", "Directory Settings" => "Hakemistoasetukset", diff --git a/apps/user_ldap/l10n/fr.php b/apps/user_ldap/l10n/fr.php index dbcaadfc2a7ec51d56d9f7a4407291a117f05c3f..44b92077b92de30d7920fbc70bb924b6731304fa 100644 --- a/apps/user_ldap/l10n/fr.php +++ b/apps/user_ldap/l10n/fr.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Port du serveur de backup (réplique)", "Disable Main Server" => "Désactiver le serveur principal", "Only connect to the replica server." => "Se connecter uniquement au serveur de replica.", -"Case insensitve LDAP server (Windows)" => "Serveur LDAP insensible à la casse (Windows)", +"Case insensitive LDAP server (Windows)" => "Serveur LDAP insensible à la casse (Windows)", "Turn off SSL certificate validation." => "Désactiver la validation du certificat SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Non recommandé, à utiliser à des fins de tests uniquement. Si la connexion ne fonctionne qu'avec cette option, importez le certificat SSL du serveur LDAP dans le serveur %s.", "Cache Time-To-Live" => "Durée de vie du cache", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Association groupe-membre", "Nested Groups" => "Groupes imbriqués", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Si activé, les groupes contenant d'autres groupes sont supportés (fonctionne uniquement si l'attribut membre du groupe contient des DNs).", +"Paging chunksize" => "Dimensionnement des paginations", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "La taille d'une part (chunksize) est utilisée pour les recherches paginées de LDAP qui peuvent retourner des résultats par lots comme une énumération d'utilisateurs ou groupes. (Configurer à 0 pour désactiver les recherches paginées de LDAP.)", "Special Attributes" => "Attributs spéciaux", "Quota Field" => "Champ du quota", "Quota Default" => "Quota par défaut", diff --git a/apps/user_ldap/l10n/gl.php b/apps/user_ldap/l10n/gl.php index 802c6d0e4359f76dbe59d01ed708c47d2924ce87..82c484bb95d44eb77786a87a8bc4d98e56fea337 100644 --- a/apps/user_ldap/l10n/gl.php +++ b/apps/user_ldap/l10n/gl.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Porto da copia de seguranza (Réplica)", "Disable Main Server" => "Desactivar o servidor principal", "Only connect to the replica server." => "Conectar só co servidor de réplica.", -"Case insensitve LDAP server (Windows)" => "Servidor LDAP que non distingue entre maiúsculas e minúsculas (Windows)", +"Case insensitive LDAP server (Windows)" => "Servidor LDAP non sensíbel a maiúsculas (Windows)", "Turn off SSL certificate validation." => "Desactiva a validación do certificado SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Non recomendado, utilizar só para probas! Se a conexión só funciona con esta opción importa o certificado SSL do servidor LDAP no seu servidor %s.", "Cache Time-To-Live" => "Tempo de persistencia da caché", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Asociación de grupos e membros", "Nested Groups" => "Grupos aniñados", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Se está activado, admítense grupos que conteñen grupos. (Só funciona se o atributo de membro de grupo conten os DN.)", +"Paging chunksize" => "Tamaño dos fragmentos paxinados", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Tamaño dos fragmentos utilizados para as buscas LDAP paxinadas, que poden devolver resultados voluminosos como usuario ou enumeración de grupo. (Se se establece a 0, desactívanse as buscas LDAP paxinadas nesas situacións.)", "Special Attributes" => "Atributos especiais", "Quota Field" => "Campo de cota", "Quota Default" => "Cota predeterminada", diff --git a/apps/user_ldap/l10n/hu_HU.php b/apps/user_ldap/l10n/hu_HU.php index 277ae96fcd48269b1c4a21ce1e960522840c089e..34daa25ce6867f462c7f129c89c6465787b6609a 100644 --- a/apps/user_ldap/l10n/hu_HU.php +++ b/apps/user_ldap/l10n/hu_HU.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "A másodkiszolgáló (replika) portszáma", "Disable Main Server" => "A fő szerver kihagyása", "Only connect to the replica server." => "Csak a másodlagos (másolati) kiszolgálóhoz kapcsolódjunk.", -"Case insensitve LDAP server (Windows)" => "Az LDAP-kiszolgáló nem tesz különbséget a kis- és nagybetűk között (Windows)", "Turn off SSL certificate validation." => "Ne ellenőrizzük az SSL-tanúsítvány érvényességét", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Használata nem javasolt (kivéve tesztelési céllal). Ha a kapcsolat csak ezzel a beállítással működik, akkor importálja az LDAP-kiszolgáló SSL tanúsítványát a(z) %s kiszolgálóra!", "Cache Time-To-Live" => "A gyorsítótár tárolási időtartama", diff --git a/apps/user_ldap/l10n/id.php b/apps/user_ldap/l10n/id.php index 03071bb1d0fa302a98c85160ce6e9b72d0334996..1d42031a4982f7efdf91d9600789b2688ce2e8b8 100644 --- a/apps/user_ldap/l10n/id.php +++ b/apps/user_ldap/l10n/id.php @@ -39,7 +39,6 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Berikan pilihan host cadangan. Harus merupakan replika dari server LDAP/AD utama.", "Backup (Replica) Port" => "Port Cadangan (Replika)", "Disable Main Server" => "Nonaktifkan Server Utama", -"Case insensitve LDAP server (Windows)" => "Server LDAP dengan kapitalisasi tidak sensitif (Windows)", "Turn off SSL certificate validation." => "matikan validasi sertivikat SSL", "Cache Time-To-Live" => "Gunakan Tembolok untuk Time-To-Live", "in seconds. A change empties the cache." => "dalam detik. perubahan mengosongkan cache", diff --git a/apps/user_ldap/l10n/it.php b/apps/user_ldap/l10n/it.php index 4436127747f68162981caa9e54533a40e69a3eb6..095a0619ee1fc0e2d48d40f3e1208358ec4c8bd6 100644 --- a/apps/user_ldap/l10n/it.php +++ b/apps/user_ldap/l10n/it.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Porta di backup (Replica)", "Disable Main Server" => "Disabilita server principale", "Only connect to the replica server." => "Collegati solo al server di replica.", -"Case insensitve LDAP server (Windows)" => "Case insensitve LDAP server (Windows)", +"Case insensitive LDAP server (Windows)" => "Server LDAP non sensibile alle maiuscole (Windows)", "Turn off SSL certificate validation." => "Disattiva il controllo del certificato SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Non consigliata, da utilizzare solo per test! Se la connessione funziona solo con questa opzione, importa il certificate SSL del server LDAP sul tuo server %s.", "Cache Time-To-Live" => "Tempo di vita della cache", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Associazione gruppo-utente ", "Nested Groups" => "Gruppi nidificati", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Quando è attivato, i gruppi che contengono altri gruppi sono supportati. (Funziona solo se l'attributo del gruppo membro contiene DN.)", +"Paging chunksize" => "Dimensione del blocco di paginazione", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Dimensione del blocco per le ricerche LDAP paginate che potrebbero restituire risultati pesanti come l'enumerazione di utenti o gruppi.(L'impostazione a 0 disabilita le ricerche LDAP paginate in questi casi.)", "Special Attributes" => "Attributi speciali", "Quota Field" => "Campo Quota", "Quota Default" => "Quota predefinita", diff --git a/apps/user_ldap/l10n/ja.php b/apps/user_ldap/l10n/ja.php index d13deafe6c3d4a909e95adcf8f99d2683a1eccb2..e7e4706c46a4d43e959f030f8ed02e08e9ba14d1 100644 --- a/apps/user_ldap/l10n/ja.php +++ b/apps/user_ldap/l10n/ja.php @@ -70,7 +70,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "バックアップ(レプリカ)ポート", "Disable Main Server" => "メインサーバーを無効にする", "Only connect to the replica server." => "レプリカサーバーにのみ接続します。", -"Case insensitve LDAP server (Windows)" => "大文字/小文字を区別しないLDAPサーバー(Windows)", "Turn off SSL certificate validation." => "SSL証明書の確認を無効にする。", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "推奨されません、テストにおいてのみ使用してください!このオプションでのみ接続が動作する場合は、LDAP サーバーのSSL証明書を %s サーバーにインポートしてください。", "Cache Time-To-Live" => "キャッシュのTTL", diff --git a/apps/user_ldap/l10n/jv.php b/apps/user_ldap/l10n/jv.php new file mode 100644 index 0000000000000000000000000000000000000000..3a1e002311cd9c1851bda1b96f71bc4d3e3e047b --- /dev/null +++ b/apps/user_ldap/l10n/jv.php @@ -0,0 +1,6 @@ + array("",""), +"_%s user found_::_%s users found_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/ka_GE.php b/apps/user_ldap/l10n/ka_GE.php index ffdf76555178e628ce8da673808ac1581a1e1fa1..3ee307b55ccb88e9986444c5e9a7f163be37b54d 100644 --- a/apps/user_ldap/l10n/ka_GE.php +++ b/apps/user_ldap/l10n/ka_GE.php @@ -37,7 +37,6 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "მიუთითეთ რაიმე ბექაფ ჰოსტი. ის უნდა იყოს ძირითადი LDAP/AD სერვერის რეპლიკა.", "Backup (Replica) Port" => "ბექაფ (რეპლიკა) პორტი", "Disable Main Server" => "გამორთეთ ძირითადი სერვერი", -"Case insensitve LDAP server (Windows)" => "LDAP server (Windows)", "Turn off SSL certificate validation." => "გამორთეთ SSL სერთიფიკატის ვალიდაცია.", "Cache Time-To-Live" => "ქეშის სიცოცხლის ხანგრძლივობა", "in seconds. A change empties the cache." => "წამებში. ცვლილება ასუფთავებს ქეშს.", diff --git a/apps/user_ldap/l10n/ko.php b/apps/user_ldap/l10n/ko.php index 5dd2151a411484c69d7461207050e601bd006768..1ae63bd4d2146228e4e8dfac309cc759da011707 100644 --- a/apps/user_ldap/l10n/ko.php +++ b/apps/user_ldap/l10n/ko.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "백업 (복제) 포트", "Disable Main Server" => "주 서버 비활성화", "Only connect to the replica server." => "복제 서버에만 연결합니다.", -"Case insensitve LDAP server (Windows)" => "서버에서 대소문자를 구분하지 않음 (Windows)", "Turn off SSL certificate validation." => "SSL 인증서 유효성 검사를 해제합니다.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "테스트 목적으로만 사용하십시오! 이 옵션을 사용해야만 연결할 수 있으면 %s 서버에 LDAP 서버의 SSL 인증서를 설치하십시오.", "Cache Time-To-Live" => "캐시 유지 시간", diff --git a/apps/user_ldap/l10n/lv.php b/apps/user_ldap/l10n/lv.php index 769f17e633884b4e05075487914bd29e5104c022..e3cb206e2d6db7b9b2830005135887e70fdf9051 100644 --- a/apps/user_ldap/l10n/lv.php +++ b/apps/user_ldap/l10n/lv.php @@ -36,7 +36,6 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Norādi rezerves serveri (nav obligāti). Tam ir jābūt galvenā LDAP/AD servera kopijai.", "Backup (Replica) Port" => "Rezerves (kopijas) ports", "Disable Main Server" => "Deaktivēt galveno serveri", -"Case insensitve LDAP server (Windows)" => "Reģistrnejutīgs LDAP serveris (Windows)", "Turn off SSL certificate validation." => "Izslēgt SSL sertifikātu validēšanu.", "Cache Time-To-Live" => "Kešatmiņas dzīvlaiks", "in seconds. A change empties the cache." => "sekundēs. Izmaiņas iztukšos kešatmiņu.", diff --git a/apps/user_ldap/l10n/nb_NO.php b/apps/user_ldap/l10n/nb_NO.php index 0b60752e9d9504796f12fb179a9dc1e24598e44b..dd4af3e759e93f24085b13f3760d7925636175cc 100644 --- a/apps/user_ldap/l10n/nb_NO.php +++ b/apps/user_ldap/l10n/nb_NO.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Reserve (Replika) Port", "Disable Main Server" => "Deaktiver hovedtjeneren", "Only connect to the replica server." => "Koble til bare replika-tjeneren.", -"Case insensitve LDAP server (Windows)" => "Case-insensitiv LDAP tjener (Windows)", "Turn off SSL certificate validation." => "Slå av SSL-sertifikat validering", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Ikke anbefalt, bruk kun for testing! Hvis tilkobling bare virker med dette valget, importer LDAP-tjenerens SSL-sertifikat i %s-serveren din.", "Cache Time-To-Live" => "Levetid i mellomlager", diff --git a/apps/user_ldap/l10n/nl.php b/apps/user_ldap/l10n/nl.php index 55e4e07033a593d93f47c74fccf86721cddf8f6b..196e5a52d120f480d26b8eb365373f0c50b77543 100644 --- a/apps/user_ldap/l10n/nl.php +++ b/apps/user_ldap/l10n/nl.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Backup (Replica) Poort", "Disable Main Server" => "Deactiveren hoofdserver", "Only connect to the replica server." => "Maak alleen een verbinding met de replica server.", -"Case insensitve LDAP server (Windows)" => "Niet-hoofdlettergevoelige LDAP server (Windows)", +"Case insensitive LDAP server (Windows)" => "Niet-hoofdlettergevoelige LDAP server (Windows)", "Turn off SSL certificate validation." => "Schakel SSL certificaat validatie uit.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Niet aanbevolen, gebruik alleen om te testen! Als de connectie alleen werkt met deze optie, importeer dan het SSL-certificaat van de LDAP-server naar uw %s server.", "Cache Time-To-Live" => "Cache time-to-live", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Groepslid associatie", "Nested Groups" => "Geneste groepen", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Wanneer ingeschakeld worden groepen binnen groepen ondersteund. (Werkt alleen als het groepslid attribuut DNs bevat)", +"Paging chunksize" => "Paging chunkgrootte", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "De chunkgrootte die wordt gebruikt voor LDAP opvragingen die in grote aantallen resulteren, zoals gebruiker- of groepsverzamelingen. (Instellen op 0 deactiveert gepagede LDAP opvragingen in dergelijke situaties.)", "Special Attributes" => "Speciale attributen", "Quota Field" => "Quota veld", "Quota Default" => "Quota standaard", diff --git a/apps/user_ldap/l10n/pl.php b/apps/user_ldap/l10n/pl.php index 5c6d3d7022e3da75c9dabd07c7e288bb2f89c1b1..988e44dbe387fbd6b195e7d487d54226aa6b0971 100644 --- a/apps/user_ldap/l10n/pl.php +++ b/apps/user_ldap/l10n/pl.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Kopia zapasowa (repliki) Port", "Disable Main Server" => "Wyłącz serwer główny", "Only connect to the replica server." => "Połącz tylko do repliki serwera.", -"Case insensitve LDAP server (Windows)" => "Wielkość liter serwera LDAP (Windows)", +"Case insensitive LDAP server (Windows)" => "Serwer LDAP nie rozróżniający wielkości liter (Windows)", "Turn off SSL certificate validation." => "Wyłączyć sprawdzanie poprawności certyfikatu SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Nie polecane, używać tylko w celu testowania! Jeśli połączenie działa tylko z tą opcją, zaimportuj certyfikat SSL serwera LDAP na swój %s.", "Cache Time-To-Live" => "Przechowuj czas życia", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Członek grupy stowarzyszenia", "Nested Groups" => "Grupy zagnieżdżone", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Kiedy włączone, grupy, które zawierają grupy, są wspierane. (Działa tylko, jeśli członek grupy ma ustawienie DNs)", +"Paging chunksize" => "Wielkość stronicowania", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Długość łańcucha jest używana do stronicowanych wyszukiwań LDAP, które mogą zwracać duże zbiory jak lista grup, czy użytkowników. (Ustawienie na 0 wyłącza stronicowane wyszukiwania w takich sytuacjach.)", "Special Attributes" => "Specjalne atrybuty", "Quota Field" => "Pole przydziału", "Quota Default" => "Przydział domyślny", diff --git a/apps/user_ldap/l10n/pt_BR.php b/apps/user_ldap/l10n/pt_BR.php index 786bee4c8ae3d0ad45d2d92b2959d0b17d45b71f..0c15694e3ff502566afa662626b5fc8b514e2a00 100644 --- a/apps/user_ldap/l10n/pt_BR.php +++ b/apps/user_ldap/l10n/pt_BR.php @@ -70,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Porta do Backup (Réplica)", "Disable Main Server" => "Desativar Servidor Principal", "Only connect to the replica server." => "Conectar-se somente ao servidor de réplica.", -"Case insensitve LDAP server (Windows)" => "Servidor LDAP sensível à caixa alta (Windows)", +"Case insensitive LDAP server (Windows)" => "Servidor LDAP(Windows) não distigue maiúscula de minúscula", "Turn off SSL certificate validation." => "Desligar validação de certificado SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Não recomendado, use-o somente para teste! Se a conexão só funciona com esta opção, importar o certificado SSL do servidor LDAP em seu servidor %s.", "Cache Time-To-Live" => "Cache Time-To-Live", @@ -90,6 +90,8 @@ $TRANSLATIONS = array( "Group-Member association" => "Associação Grupo-Membro", "Nested Groups" => "Grupos Aninhados", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Quando habilitado, os grupos que contêm os grupos são suportados. (Só funciona se o atributo de membro de grupo contém DNs.)", +"Paging chunksize" => "Bloco de paginação", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Tamanho do bloco usado para pesquisas LDAP paginados que podem retornar resultados volumosos como usuário ou grupo de enumeração. (Defini-lo 0 desativa paginada pesquisas LDAP nessas situações.)", "Special Attributes" => "Atributos Especiais", "Quota Field" => "Campo de Cota", "Quota Default" => "Cota Padrão", diff --git a/apps/user_ldap/l10n/pt_PT.php b/apps/user_ldap/l10n/pt_PT.php index 37142c8175aa1e2d0587cfbf49cb1bb366a43412..e2754785c650518c8ff240abedf77012e69e640e 100644 --- a/apps/user_ldap/l10n/pt_PT.php +++ b/apps/user_ldap/l10n/pt_PT.php @@ -65,7 +65,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Porta do servidor de backup (Replica)", "Disable Main Server" => "Desactivar servidor principal", "Only connect to the replica server." => "Ligar apenas ao servidor de réplicas.", -"Case insensitve LDAP server (Windows)" => "Servidor LDAP (Windows) não sensível a maiúsculas.", "Turn off SSL certificate validation." => "Desligar a validação de certificado SSL.", "Cache Time-To-Live" => "Cache do tempo de vida dos objetos no servidor", "in seconds. A change empties the cache." => "em segundos. Uma alteração esvazia a cache.", diff --git a/apps/user_ldap/l10n/ro.php b/apps/user_ldap/l10n/ro.php index 0214be3f787fb7d32637e8633d860fef5bb71688..26394db0f85d320b08780ce8df5055770047a5f3 100644 --- a/apps/user_ldap/l10n/ro.php +++ b/apps/user_ldap/l10n/ro.php @@ -19,7 +19,6 @@ $TRANSLATIONS = array( "Back" => "Înapoi", "Continue" => "Continuă", "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Atenție Modulul PHP LDAP nu este instalat, infrastructura nu va funcționa. Contactează administratorul sistemului pentru al instala.", -"Case insensitve LDAP server (Windows)" => "Server LDAP insensibil la majuscule (Windows)", "Turn off SSL certificate validation." => "Oprește validarea certificatelor SSL ", "in seconds. A change empties the cache." => "în secunde. O schimbare curăță memoria tampon.", "User Display Name Field" => "Câmpul cu numele vizibil al utilizatorului", diff --git a/apps/user_ldap/l10n/ru.php b/apps/user_ldap/l10n/ru.php index d9685368cbcf8064a990f7aedb91b43a3fcc4f18..2cf331d24c0cff64a5594fb4d99007bf352be680 100644 --- a/apps/user_ldap/l10n/ru.php +++ b/apps/user_ldap/l10n/ru.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Порт резервного сервера", "Disable Main Server" => "Отключить главный сервер", "Only connect to the replica server." => "Подключаться только к серверу-реплике.", -"Case insensitve LDAP server (Windows)" => "Нечувствительный к регистру сервер LDAP (Windows)", "Turn off SSL certificate validation." => "Отключить проверку сертификата SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Не рекомендуется, используйте только в режиме тестирования! Если соединение работает только с этой опцией, импортируйте на ваш %s сервер SSL-сертификат сервера LDAP.", "Cache Time-To-Live" => "Кэш времени жизни", diff --git a/apps/user_ldap/l10n/sk_SK.php b/apps/user_ldap/l10n/sk_SK.php index 460064593ee72566bbd13714fb63a84a82ffaf28..edda4244336060fb18f9086adfdf6426a40b8635 100644 --- a/apps/user_ldap/l10n/sk_SK.php +++ b/apps/user_ldap/l10n/sk_SK.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Záložný server (kópia) port", "Disable Main Server" => "Zakázať hlavný server", "Only connect to the replica server." => "Pripojiť sa len k záložnému serveru.", -"Case insensitve LDAP server (Windows)" => "LDAP server nerozlišuje veľkosť znakov (Windows)", "Turn off SSL certificate validation." => "Vypnúť overovanie SSL certifikátu.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Neodporúčané, použite iba pri testovaní! Pokiaľ spojenie funguje iba z daným nastavením, importujte SSL certifikát LDAP servera do vášho %s servera.", "Cache Time-To-Live" => "Životnosť objektov vo vyrovnávacej pamäti", diff --git a/apps/user_ldap/l10n/sl.php b/apps/user_ldap/l10n/sl.php index b2a21b6e0296ee9901a4c8517001db62b5e6ad4e..54c91103a3e368b1c982d1d5eb4725aebe85af60 100644 --- a/apps/user_ldap/l10n/sl.php +++ b/apps/user_ldap/l10n/sl.php @@ -67,7 +67,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Vrata varnostne kopije (replike)", "Disable Main Server" => "Onemogoči glavni strežnik", "Only connect to the replica server." => "Poveži le s podvojenim strežnikom.", -"Case insensitve LDAP server (Windows)" => "Strežnik LDAP ne upošteva velikosti črk (Windows)", "Turn off SSL certificate validation." => "Onemogoči določanje veljavnosti potrdila SSL.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Možnosti ni priporočljivo uporabiti; namenjena je zgolj preizkušanju! Če deluje povezava le s to možnostjo, je treba uvoziti potrdilo SSL strežnika LDAP na strežnik %s.", "Cache Time-To-Live" => "Predpomni podatke TTL", @@ -85,6 +84,7 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Eno osnovno ime skupine na vrstico", "Group Search Attributes" => "Skupinski atributi iskanja", "Group-Member association" => "Povezava član-skupina", +"Nested Groups" => "Gnezdene skupine", "Special Attributes" => "Posebni atributi", "Quota Field" => "Polje količinske omejitve", "Quota Default" => "Privzeta količinska omejitev", diff --git a/apps/user_ldap/l10n/sq.php b/apps/user_ldap/l10n/sq.php index 0f18ac02351ea26515bebccdc58945a97716aad2..03ff204bbca74623fc36fac4b41a59b847738ccf 100644 --- a/apps/user_ldap/l10n/sq.php +++ b/apps/user_ldap/l10n/sq.php @@ -38,7 +38,6 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Jepni një pritës rezervë. Duhet të jetë replikimi i serverit AD/LDAP kryesor.", "Backup (Replica) Port" => "Porta rezervë (Replika)", "Disable Main Server" => "Ç'aktivizoni serverin kryesor", -"Case insensitve LDAP server (Windows)" => " Server LDAP i pavëmëndshëm ndaj gërmëzimit të madh apo jo (Windows)", "Turn off SSL certificate validation." => "Ç'aktivizoni kontrollin e certifikatës SSL.", "Cache Time-To-Live" => "Cache Time-To-Live", "in seconds. A change empties the cache." => "në sekonda Ndryshimi boshatis 'cache'-n.", diff --git a/apps/user_ldap/l10n/sr.php b/apps/user_ldap/l10n/sr.php index d2ce2cf08b61052c4effff62ecc81863885fbc5a..fb016fdd17e895e46f1bc7d295b2622d422aafb2 100644 --- a/apps/user_ldap/l10n/sr.php +++ b/apps/user_ldap/l10n/sr.php @@ -14,7 +14,6 @@ $TRANSLATIONS = array( "Password" => "Лозинка", "For anonymous access, leave DN and Password empty." => "За анониман приступ, оставите поља DN и лозинка празним.", "Back" => "Назад", -"Case insensitve LDAP server (Windows)" => "LDAP сервер осетљив на велика и мала слова (Windows)", "Turn off SSL certificate validation." => "Искључите потврду SSL сертификата.", "in seconds. A change empties the cache." => "у секундама. Промена испражњава кеш меморију.", "User Display Name Field" => "Име приказа корисника", diff --git a/apps/user_ldap/l10n/sv.php b/apps/user_ldap/l10n/sv.php index 0108cfcb0e4f530eea3e849a92dbf335ee049281..2a4f8b19655ff98837a6f6025d5255b74278b4db 100644 --- a/apps/user_ldap/l10n/sv.php +++ b/apps/user_ldap/l10n/sv.php @@ -33,12 +33,14 @@ $TRANSLATIONS = array( "Save" => "Spara", "Test Configuration" => "Testa konfigurationen", "Help" => "Hjälp", +"Groups meeting these criteria are available in %s:" => "Grupper som uppfyller dessa kriterier finns i %s:", "only those object classes:" => "Endast de objekt-klasserna:", "only from those groups:" => "endast ifrån de här grupperna:", "Edit raw filter instead" => "Redigera rått filter istället", "Raw LDAP filter" => "Rått LDAP-filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "Filtret specifierar vilka LDAD-grupper som ska ha åtkomst till %s instans", "groups found" => "grupper hittade", +"Users login with this attribute:" => "Användare loggar in med detta attribut:", "LDAP Username:" => "LDAP användarnamn:", "LDAP Email Address:" => "LDAP e-postadress:", "Other Attributes:" => "Övriga attribut:", @@ -53,6 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "För anonym åtkomst, lämna DN och lösenord tomt.", "One Base DN per line" => "Ett Start DN per rad", "You can specify Base DN for users and groups in the Advanced tab" => "Du kan ange start DN för användare och grupper under fliken Avancerat", +"Limit %s access to users meeting these criteria:" => "Begränsa %s tillgång till användare som uppfyller dessa kriterier:", "The filter specifies which LDAP users shall have access to the %s instance." => "Filtret specifierar vilka LDAP-användare som skall ha åtkomst till %s instans", "users found" => "användare funna", "Back" => "Tillbaka", @@ -67,7 +70,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Säkerhetskopierins-port (Replika)", "Disable Main Server" => "Inaktivera huvudserver", "Only connect to the replica server." => "Anslut endast till replikaservern.", -"Case insensitve LDAP server (Windows)" => "LDAP-servern är okänslig för gemener och versaler (Windows)", +"Case insensitive LDAP server (Windows)" => "om okänslig LDAP-server (Windows)", "Turn off SSL certificate validation." => "Stäng av verifiering av SSL-certifikat.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Rekommenderas inte, använd endast för test! Om anslutningen bara fungerar med denna inställning behöver du importera LDAP-serverns SSL-certifikat till din %s server.", "Cache Time-To-Live" => "Cache Time-To-Live", @@ -85,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "En Grupp start DN per rad", "Group Search Attributes" => "Gruppsökningsattribut", "Group-Member association" => "Attribut för gruppmedlemmar", +"Nested Groups" => "Undergrupper", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "När den är påslagen, stöds grupper som innehåller grupper. (Fungerar endast om gruppmedlemmens attribut innehåller DNs.)", +"Paging chunksize" => "Paging klusterstorlek", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Klusterstorlek som används för paged LDAP sökningar som kan komma att returnera skrymmande resultat som uppräknande av användare eller grupper. (Inställning av denna till 0 inaktiverar paged LDAP sökningar i de situationerna)", "Special Attributes" => "Specialattribut", "Quota Field" => "Kvotfält", "Quota Default" => "Datakvot standard", diff --git a/apps/user_ldap/l10n/ta_LK.php b/apps/user_ldap/l10n/ta_LK.php index c7efcf05894e65d6a7ed4f87373a1bd760140afb..27a3068f963b7bdea64aec8b1f06026a522fd5a3 100644 --- a/apps/user_ldap/l10n/ta_LK.php +++ b/apps/user_ldap/l10n/ta_LK.php @@ -13,7 +13,6 @@ $TRANSLATIONS = array( "Password" => "கடவுச்சொல்", "You can specify Base DN for users and groups in the Advanced tab" => "நீங்கள் பயனாளர்களுக்கும் மேன்மை தத்தலில் உள்ள குழுவிற்கும் தள DN ஐ குறிப்பிடலாம் ", "Back" => "பின்னுக்கு", -"Case insensitve LDAP server (Windows)" => "உணர்ச்சியான LDAP சேவையகம் (சாளரங்கள்)", "Turn off SSL certificate validation." => "SSL சான்றிதழின் செல்லுபடியை நிறுத்திவிடவும்", "in seconds. A change empties the cache." => "செக்கன்களில். ஒரு மாற்றம் இடைமாற்றுநினைவகத்தை வெற்றிடமாக்கும்.", "User Display Name Field" => "பயனாளர் காட்சிப்பெயர் புலம்", diff --git a/apps/user_ldap/l10n/th_TH.php b/apps/user_ldap/l10n/th_TH.php index 2202a2f0a837178991396803c6bb8026f0fc7594..1c6dbe0473f785ab6949794f728a05748e3b6552 100644 --- a/apps/user_ldap/l10n/th_TH.php +++ b/apps/user_ldap/l10n/th_TH.php @@ -31,7 +31,6 @@ $TRANSLATIONS = array( "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "คำเตือน: โมดูล PHP LDAP ยังไม่ได้ถูกติดตั้ง, ระบบด้านหลังจะไม่สามารถทำงานได้ กรุณาติดต่อผู้ดูแลระบบของคุณเพื่อทำการติดตั้งโมดูลดังกล่าว", "Connection Settings" => "ตั้งค่าการเชื่อมต่อ", "Disable Main Server" => "ปิดใช้งานเซิร์ฟเวอร์หลัก", -"Case insensitve LDAP server (Windows)" => "เซิร์ฟเวอร์ LDAP ประเภท Case insensitive (วินโดวส์)", "Turn off SSL certificate validation." => "ปิดใช้งานการตรวจสอบความถูกต้องของใบรับรองความปลอดภัย SSL", "in seconds. A change empties the cache." => "ในอีกไม่กี่วินาที ระบบจะเปลี่ยนแปลงข้อมูลในแคชให้ว่างเปล่า", "Directory Settings" => "ตั้งค่าไดเร็กทอรี่", diff --git a/apps/user_ldap/l10n/tr.php b/apps/user_ldap/l10n/tr.php index fa829a7427c4eb5a9241b687201b652e03906e15..48e39c8523cce56e9b0e6ab5bbf9f56940b7bfb5 100644 --- a/apps/user_ldap/l10n/tr.php +++ b/apps/user_ldap/l10n/tr.php @@ -45,51 +45,53 @@ $TRANSLATIONS = array( "LDAP Email Address:" => "LDAP E-posta Adresi:", "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\"", -"Add Server Configuration" => "Sunucu Uyunlama birlemek ", +"Add Server Configuration" => "Sunucu Yapılandırması Ekle", "Host" => "Sunucu", -"You can omit the protocol, except you require SSL. Then start with ldaps://" => "Protokol atlamak edesin, sadece SSL istiyorsaniz. O zaman, idapsile baslamak. ", +"You can omit the protocol, except you require SSL. Then start with ldaps://" => "SSL gerektirmediğiniz takdirde protokol belirtmeyebilirsiniz. Ardından ldaps:// ile başlayın", "Port" => "Port", "User DN" => "Kullanıcı DN", -"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." => "DN musterinin, kimle baglamaya yapacagiz,meselâ uid=agent.dc mesela, dc=com Gecinme adisiz ici, DN ve Parola bos birakmak. ", +"The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." => "İstemci kullanıcısının yapılacağı atamanın DN'i örn. uid=agent,dc=örnek,dc=com. Anonim erişim için DN ve Parolayı boş bırakın.", "Password" => "Parola", "For anonymous access, leave DN and Password empty." => "Anonim erişim için DN ve Parola alanlarını boş bırakın.", -"One Base DN per line" => "Bir Tabani DN herbir dizi. ", -"You can specify Base DN for users and groups in the Advanced tab" => "Base DN kullanicileri ve kaynaklari icin tablosu Advanced tayin etmek ederiz. ", +"One Base DN per line" => "Her satırda tek bir Base DN", +"You can specify Base DN for users and groups in the Advanced tab" => "Gelişmiş sekmesinde kullanıcılar ve gruplar için Base DN belirtebilirsiniz.", "Limit %s access to users meeting these criteria:" => "%s erişimini, şu kriterle eşleşen kullanıcılara sınırla:", "The filter specifies which LDAP users shall have access to the %s instance." => "Filtre, %s örneğine erişmesi gereken LDAP kullanıcılarını belirtir.", "users found" => "kullanıcı bulundu", "Back" => "Geri", "Continue" => "Devam et", "Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "Uyarı: user_ldap ve user_webdavauth uygulamaları uyumlu değil. Beklenmedik bir davranışla karşılaşabilirsiniz. Lütfen ikisinden birini devre dışı bırakmak için sistem yöneticinizle iletişime geçin.", -"Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Ihbar Modulu PHP LDAP yuklemdi degil, backend calismacak. Lutfen sistem yonetici sormak yuklemek icin.", +"Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Uyarı: PHP LDAP modülü kurulu değil, arka uç çalışmayacak. Lütfen kurulumu için sistem yöneticinizle iletişime geçin.", "Connection Settings" => "Bağlantı ayarları", "Configuration Active" => "Yapılandırma Etkin", -"When unchecked, this configuration will be skipped." => "Ne zaman iptal, bu uynnlama isletici ", -"Backup (Replica) Host" => "Sigorta Kopya Cephe ", -"Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Bir kopya cevre vermek, kopya sunucu onemli olmali. ", -"Backup (Replica) Port" => "Kopya Port ", +"When unchecked, this configuration will be skipped." => "İşaretli değilse, bu yapılandırma atlanacaktır.", +"Backup (Replica) Host" => "Yedek (Replica) Sunucu", +"Give an optional backup host. It must be a replica of the main LDAP/AD server." => "İsteğe bağlı bir yedek sunucusu belirtin. Ana LDAP/AD sunucusunun bir kopyası olmalıdır.", +"Backup (Replica) Port" => "Yedek (Replica) Bağlantı Noktası", "Disable Main Server" => "Ana sunucuyu devredışı birak", "Only connect to the replica server." => "Sadece kopya sunucuya bağlan.", -"Case insensitve LDAP server (Windows)" => "Dusme sunucu LDAP zor degil. (Windows)", +"Case insensitive LDAP server (Windows)" => "Büyük küçük harf duyarsız LDAP sunucusu (Windows)", "Turn off SSL certificate validation." => "SSL sertifika doğrulamasını kapat.", "Not recommended, use it for testing only! If connection only works with this option, import the LDAP server's SSL certificate in your %s server." => "Önerilmez, sadece test için kullanın! Eğer bağlantı sadece bu seçenekle çalışıyorsa %s sunucunuza LDAP sunucusunun SSL sertifikasını ekleyin.", -"Cache Time-To-Live" => "Cache Time-To-Live ", +"Cache Time-To-Live" => "Önbellek Time-To-Live Değeri", "in seconds. A change empties the cache." => "saniye cinsinden. Bir değişiklik önbelleği temizleyecektir.", -"Directory Settings" => "Parametrar Listesin Adresinin ", -"User Display Name Field" => "Ekran Adi Kullanici, (Alan Adi Kullanici Ekrane)", +"Directory Settings" => "Dizin Ayarları", +"User Display Name Field" => "Kullanıcı Görünen Ad Alanı", "The LDAP attribute to use to generate the user's display name." => "Kullanıcının görünen adını oluşturmak için kullanılacak LDAP niteliği.", "Base User Tree" => "Temel Kullanıcı Ağacı", -"One User Base DN per line" => "Bir Temel Kullanici DN her dizgi ", -"User Search Attributes" => "Kategorii Arama Kullanici ", +"One User Base DN per line" => "Her satırda Tek Kullanıcı Base DN'i", +"User Search Attributes" => "Kullanıcı Arama Nitelikleri", "Optional; one attribute per line" => "Tercihe bağlı; her bir satırda bir öznitelik", -"Group Display Name Field" => "Grub Ekrane Alani Adi", +"Group Display Name Field" => "Grup Görünen Ad Alanı", "The LDAP attribute to use to generate the groups's display name." => "Grubun görünen adını oluşturmak için kullanılacak LDAP niteliği.", "Base Group Tree" => "Temel Grup Ağacı", -"One Group Base DN per line" => "Bir Grubu Tabani DN her dizgi. ", -"Group Search Attributes" => "Kategorii Arama Grubu", +"One Group Base DN per line" => "Her satırda Tek Grup Base DN'i", +"Group Search Attributes" => "Grup Arama Nitelikleri", "Group-Member association" => "Grup-Üye işbirliği", "Nested Groups" => "İç içe Gruplar", "When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Etkinleştirildiğinde, grup içeren gruplar desteklenir (Sadece grup üyesi DN niteliği içeriyorsa çalışır).", +"Paging chunksize" => "Sayfalama yığın boyutu", +"Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)" => "Yığın boyutu, kullanıcı veya grup numaralandırması benzeri hantal sonuçlar döndürebilen sayfalandırılmış LDAP aramaları için kullanılır. (0 yapmak bu durumlarda sayfalandırılmış LDAP aramalarını devre dışı bırakır.)", "Special Attributes" => "Özel Öznitelikler", "Quota Field" => "Kota Alanı", "Quota Default" => "Öntanımlı Kota", diff --git a/apps/user_ldap/l10n/uk.php b/apps/user_ldap/l10n/uk.php index e87348ec44d365fd3e0f778e15c875a14acec310..5f4db6d5a03b7b855547e4b92f306b8a8b4e8a38 100644 --- a/apps/user_ldap/l10n/uk.php +++ b/apps/user_ldap/l10n/uk.php @@ -39,7 +39,6 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Вкажіть додатковий резервний сервер. Він повинен бути копією головного LDAP/AD сервера.", "Backup (Replica) Port" => "Порт сервера для резервних копій", "Disable Main Server" => "Вимкнути Головний Сервер", -"Case insensitve LDAP server (Windows)" => "Нечутливий до регістру LDAP сервер (Windows)", "Turn off SSL certificate validation." => "Вимкнути перевірку SSL сертифіката.", "Cache Time-To-Live" => "Час актуальності Кеша", "in seconds. A change empties the cache." => "в секундах. Зміна очищує кеш.", diff --git a/apps/user_ldap/l10n/vi.php b/apps/user_ldap/l10n/vi.php index 84d001cb5966fea072203000979d260d53d02065..21b9783897ea66a044c7ca08f60e049fb05ab8b2 100644 --- a/apps/user_ldap/l10n/vi.php +++ b/apps/user_ldap/l10n/vi.php @@ -21,7 +21,6 @@ $TRANSLATIONS = array( "Connection Settings" => "Connection Settings", "Backup (Replica) Port" => "Cổng sao lưu (Replica)", "Disable Main Server" => "Tắt máy chủ chính", -"Case insensitve LDAP server (Windows)" => "Trường hợp insensitve LDAP máy chủ (Windows)", "Turn off SSL certificate validation." => "Tắt xác thực chứng nhận SSL", "in seconds. A change empties the cache." => "trong vài giây. Một sự thay đổi bộ nhớ cache.", "Directory Settings" => "Directory Settings", diff --git a/apps/user_ldap/l10n/zh_CN.php b/apps/user_ldap/l10n/zh_CN.php index aae100ef9adf8548059a0866bb595b6649073e0c..d56f394f644021f7a85f68f5f3e8806c822b66da 100644 --- a/apps/user_ldap/l10n/zh_CN.php +++ b/apps/user_ldap/l10n/zh_CN.php @@ -42,7 +42,6 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "备份 (镜像) 端口", "Disable Main Server" => "禁用主服务器", "Only connect to the replica server." => "只能连接到复制服务器", -"Case insensitve LDAP server (Windows)" => "大小写敏感LDAP服务器(Windows)", "Turn off SSL certificate validation." => "关闭SSL证书验证", "Cache Time-To-Live" => "缓存存活时间", "in seconds. A change empties the cache." => "以秒计。修改将清空缓存。", diff --git a/apps/user_ldap/l10n/zh_TW.php b/apps/user_ldap/l10n/zh_TW.php index a7ae04cd167850a26f39fe7326e98c690b1465fb..a0975b92238d286b33a223e660e0797600280f57 100644 --- a/apps/user_ldap/l10n/zh_TW.php +++ b/apps/user_ldap/l10n/zh_TW.php @@ -41,7 +41,6 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "可以選擇性設定備用主機,必須是 LDAP/AD 中央伺服器的複本。", "Backup (Replica) Port" => "備用(複本)連接埠", "Disable Main Server" => "停用主伺服器", -"Case insensitve LDAP server (Windows)" => "不區分大小寫的 LDAP 伺服器 (Windows)", "Turn off SSL certificate validation." => "關閉 SSL 憑證檢查", "Cache Time-To-Live" => "快取的存活時間", "in seconds. A change empties the cache." => "以秒為單位。變更後會清空快取。", diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index d42b1c05820ce8b85092034853057610e6c009a2..c9ed1e648a230c07429737da0e9260167c50c3a8 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -77,6 +77,7 @@ class Configuration { 'ldapExpertUUIDGroupAttr' => null, 'lastJpegPhotoLookup' => null, 'ldapNestedGroups' => false, + 'ldapPagingSize' => null, ); /** @@ -344,6 +345,7 @@ class Configuration { 'has_memberof_filter_support' => 0, 'last_jpegPhoto_lookup' => 0, 'ldap_nested_groups' => 0, + 'ldap_paging_size' => 500, ); } @@ -395,7 +397,8 @@ class Configuration { 'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr', 'has_memberof_filter_support' => 'hasMemberOfFilterSupport', 'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup', - 'ldap_nested_groups' => 'ldapNestedGroups', + 'ldap_nested_groups' => 'ldapNestedGroups', + 'ldap_paging_size' => 'ldapPagingSize', ); return $array; } diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index e79090febc14d47015accbbca9553b818110a9ae..3854af617c11afaa21548d1f178e019dfb8d2077 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -869,12 +869,14 @@ class Wizard extends LDAPUtility { * @param string $attr the attribute of which a list of values shall be returned * @param $lfw bool, whether the last filter is a wildcard which shall not * be processed if there were already findings, defaults to true + * @param int $dnReadLimit the amount of how many DNs should be analyzed. + * The lower, the faster * @param string $maxF string. if not null, this variable will have the filter that * yields most result entries * @return mixed, an array with the values on success, false otherwise * */ - private function cumulativeSearchOnAttribute($filters, $attr, $lfw = true, &$maxF = null) { + public function cumulativeSearchOnAttribute($filters, $attr, $lfw = true, $dnReadLimit = 3, &$maxF = null) { $dnRead = array(); $foundItems = array(); $maxEntries = 0; @@ -884,11 +886,16 @@ class Wizard extends LDAPUtility { } $base = $this->configuration->ldapBase[0]; $cr = $this->getConnection(); - if(!is_resource($cr)) { + if(!$this->ldap->isResource($cr)) { return false; } + $lastFilter = null; + if(isset($filters[count($filters)-1])) { + $lastFilter = $filters[count($filters)-1]; + } foreach($filters as $filter) { - if($lfw && count($foundItems) > 0) { + if($lfw && $lastFilter === $filter && count($foundItems) > 0) { + //skip when the filter is a wildcard and results were found continue; } $rr = $this->ldap->search($cr, $base, $filter, array($attr)); @@ -902,8 +909,10 @@ class Wizard extends LDAPUtility { $maxEntries = $entries; $maxF = $filter; } + $dnReadCount = 0; do { $entry = $this->ldap->$getEntryFunc($cr, $rr); + $getEntryFunc = 'nextEntry'; if(!$this->ldap->isResource($entry)) { continue 2; } @@ -916,13 +925,14 @@ class Wizard extends LDAPUtility { $state = $this->getAttributeValuesFromEntry($attributes, $attr, $newItems); + $dnReadCount++; $foundItems = array_merge($foundItems, $newItems); $this->resultCache[$dn][$attr] = $newItems; $dnRead[] = $dn; - $getEntryFunc = 'nextEntry'; $rr = $entry; //will be expected by nextEntry next round - } while($state === self::LRESULT_PROCESSED_SKIP - || $this->ldap->isResource($entry)); + } while(($state === self::LRESULT_PROCESSED_SKIP + || $this->ldap->isResource($entry)) + && ($dnReadLimit === 0 || $dnReadCount < $dnReadLimit)); } } @@ -950,9 +960,19 @@ class Wizard extends LDAPUtility { $objectclasses[$key] = $p.$value; } $maxEntryObjC = ''; + + //how deep to dig? + //When looking for objectclasses, testing few entries is sufficient, + //when looking for group we need to get all names, though. + if(strtolower($attr) === 'objectclass') { + $dig = 3; + } else { + $dig = 0; + } + $availableFeatures = $this->cumulativeSearchOnAttribute($objectclasses, $attr, - true, $maxEntryObjC); + true, $dig, $maxEntryObjC); if(is_array($availableFeatures) && count($availableFeatures) > 0) { natcasesort($availableFeatures); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 79c4ae224c3b6366fc214445fbc217e625fb6b81..0a111225a70e7b90cdbf469470a62f0a6b8aea8d 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -1,5 +1,5 @@
-
+
    $title) { ?>
  • @@ -23,7 +23,7 @@

    -

    >

    +

    >


@@ -37,6 +37,7 @@

+

t('Special Attributes'));?>

diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php new file mode 100644 index 0000000000000000000000000000000000000000..ecbd42319e319706f791fde97bcca59c4d0b7ddf --- /dev/null +++ b/apps/user_ldap/tests/group_ldap.php @@ -0,0 +1,115 @@ + +* +* 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 . +* +*/ + +namespace OCA\user_ldap\tests; + +namespace OCA\user_ldap\tests; + +use \OCA\user_ldap\GROUP_LDAP as GroupLDAP; +use \OCA\user_ldap\lib\Access; +use \OCA\user_ldap\lib\Connection; +use \OCA\user_ldap\lib\ILDAPWrapper; + +class Test_Group_Ldap extends \PHPUnit_Framework_TestCase { + private function getAccessMock() { + static $conMethods; + static $accMethods; + + if(is_null($conMethods) || is_null($accMethods)) { + $conMethods = get_class_methods('\OCA\user_ldap\lib\Connection'); + $accMethods = get_class_methods('\OCA\user_ldap\lib\Access'); + } + $lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); + $connector = $this->getMock('\OCA\user_ldap\lib\Connection', + $conMethods, + array($lw, null, null)); + $access = $this->getMock('\OCA\user_ldap\lib\Access', + $accMethods, + array($connector, $lw)); + + return $access; + } + + private function enableGroups($access) { + $access->connection->expects($this->any()) + ->method('__get') + ->will($this->returnCallback(function($name) { +// if($name === 'ldapLoginFilter') { +// return '%uid'; +// } + return 1; + })); + } + + public function testCountEmptySearchString() { + $access = $this->getAccessMock(); + + $this->enableGroups($access); + + $access->expects($this->any()) + ->method('groupname2dn') + ->will($this->returnValue('cn=group,dc=foo,dc=bar')); + + $access->expects($this->any()) + ->method('readAttribute') + ->will($this->returnValue(array('u11', 'u22', 'u33', 'u34'))); + + $groupBackend = new GroupLDAP($access); + $users = $groupBackend->countUsersInGroup('group'); + + $this->assertSame(4, $users); + } + + public function testCountWithSearchString() { + $access = $this->getAccessMock(); + + $this->enableGroups($access); + + $access->expects($this->any()) + ->method('groupname2dn') + ->will($this->returnValue('cn=group,dc=foo,dc=bar')); + + $access->expects($this->any()) + ->method('readAttribute') + ->will($this->returnCallback(function($name) { + //the search operation will call readAttribute, thus we need + //to anaylze the "dn". All other times we just need to return + //something that is neither null or false, but once an array + //with the users in the group – so we do so all other times for + //simplicicity. + if(strpos($name, 'u') === 0) { + return strpos($name, '3'); + } + return array('u11', 'u22', 'u33', 'u34'); + })); + + $access->expects($this->any()) + ->method('dn2username') + ->will($this->returnValue('foobar')); + + $groupBackend = new GroupLDAP($access); + $users = $groupBackend->countUsersInGroup('group', '3'); + + $this->assertSame(2, $users); + } + +} \ No newline at end of file diff --git a/apps/user_ldap/tests/wizard.php b/apps/user_ldap/tests/wizard.php new file mode 100644 index 0000000000000000000000000000000000000000..2b5cabc705d2a18b252c9b8ae930e9acd005e32e --- /dev/null +++ b/apps/user_ldap/tests/wizard.php @@ -0,0 +1,210 @@ +. +* +*/ + +namespace OCA\user_ldap\tests; + +use \OCA\user_ldap\lib\Wizard; + +// use \OCA\user_ldap\USER_LDAP as UserLDAP; +// use \OCA\user_ldap\lib\Access; +// use \OCA\user_ldap\lib\Configuration; +// use \OCA\user_ldap\lib\ILDAPWrapper; + +class Test_Wizard extends \PHPUnit_Framework_TestCase { + public function setUp() { + //we need to make sure the consts are defined, otherwise tests will fail + //on systems without php5_ldap + $ldapConsts = array('LDAP_OPT_PROTOCOL_VERSION', + 'LDAP_OPT_REFERRALS', 'LDAP_OPT_NETWORK_TIMEOUT'); + foreach($ldapConsts as $const) { + if(!defined($const)) { + define($const, 42); + } + } + } + + private function getWizardAndMocks() { + static $conMethods; + + if(is_null($conMethods)) { + $conMethods = get_class_methods('\OCA\user_ldap\lib\Configuration'); + } + $lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); + $conf = $this->getMock('\OCA\user_ldap\lib\Configuration', + $conMethods, + array($lw, null, null)); + return array(new Wizard($conf, $lw), $conf, $lw); + } + + private function prepareLdapWrapperForConnections(&$ldap) { + $ldap->expects($this->once()) + ->method('connect') + //dummy value, usually invalid + ->will($this->returnValue(true)); + + $ldap->expects($this->exactly(3)) + ->method('setOption') + ->will($this->returnValue(true)); + + $ldap->expects($this->once()) + ->method('bind') + ->will($this->returnValue(true)); + + } + + public function testCumulativeSearchOnAttributeLimited() { + list($wizard, $configuration, $ldap) = $this->getWizardAndMocks(); + + $configuration->expects($this->any()) + ->method('__get') + ->will($this->returnCallback(function($name) { + if($name === 'ldapBase') { + return array('base'); + } + return null; + })); + + $this->prepareLdapWrapperForConnections($ldap); + + $ldap->expects($this->any()) + ->method('isResource') + ->will($this->returnValue(true)); + + $ldap->expects($this->exactly(2)) + ->method('search') + //dummy value, usually invalid + ->will($this->returnValue(true)); + + $ldap->expects($this->exactly(2)) + ->method('countEntries') + //an is_resource check will follow, so we need to return a dummy resource + ->will($this->returnValue(23)); + + //5 DNs per filter means 2x firstEntry and 8x nextEntry + $ldap->expects($this->exactly(2)) + ->method('firstEntry') + //dummy value, usually invalid + ->will($this->returnValue(true)); + + $ldap->expects($this->exactly(8)) + ->method('nextEntry') + //dummy value, usually invalid + ->will($this->returnValue(true)); + + $ldap->expects($this->exactly(10)) + ->method('getAttributes') + //dummy value, usually invalid + ->will($this->returnValue(array('cn' => array('foo'), 'count' => 1))); + + global $uidnumber; + $uidnumber = 1; + $ldap->expects($this->exactly(10)) + ->method('getDN') + //dummy value, usually invalid + ->will($this->returnCallback(function($a, $b) { + global $uidnumber; + return $uidnumber++; + })); + + # The following expectations are the real test # + $filters = array('f1', 'f2', '*'); + $wizard->cumulativeSearchOnAttribute($filters, 'cn', true, 5); + unset($uidnumber); + } + + public function testCumulativeSearchOnAttributeUnlimited() { + list($wizard, $configuration, $ldap) = $this->getWizardAndMocks(); + + $configuration->expects($this->any()) + ->method('__get') + ->will($this->returnCallback(function($name) { + if($name === 'ldapBase') { + return array('base'); + } + return null; + })); + + $this->prepareLdapWrapperForConnections($ldap); + + $ldap->expects($this->any()) + ->method('isResource') + ->will($this->returnCallback(function($r) { + if($r === true) { + return true; + } + if($r % 24 === 0) { + global $uidnumber; + $uidnumber++; + return false; + } + return true; + })); + + $ldap->expects($this->exactly(2)) + ->method('search') + //dummy value, usually invalid + ->will($this->returnValue(true)); + + $ldap->expects($this->exactly(2)) + ->method('countEntries') + //an is_resource check will follow, so we need to return a dummy resource + ->will($this->returnValue(23)); + + //5 DNs per filter means 2x firstEntry and 8x nextEntry + $ldap->expects($this->exactly(2)) + ->method('firstEntry') + //dummy value, usually invalid + ->will($this->returnCallback(function($r) { + global $uidnumber; + return $uidnumber; + })); + + $ldap->expects($this->exactly(46)) + ->method('nextEntry') + //dummy value, usually invalid + ->will($this->returnCallback(function($r) { + global $uidnumber; + return $uidnumber; + })); + + $ldap->expects($this->exactly(46)) + ->method('getAttributes') + //dummy value, usually invalid + ->will($this->returnValue(array('cn' => array('foo'), 'count' => 1))); + + global $uidnumber; + $uidnumber = 1; + $ldap->expects($this->exactly(46)) + ->method('getDN') + //dummy value, usually invalid + ->will($this->returnCallback(function($a, $b) { + global $uidnumber; + return $uidnumber++; + })); + + # The following expectations are the real test # + $filters = array('f1', 'f2', '*'); + $wizard->cumulativeSearchOnAttribute($filters, 'cn', true, 0); + unset($uidnumber); + } + +} \ No newline at end of file diff --git a/apps/user_webdavauth/appinfo/info.xml b/apps/user_webdavauth/appinfo/info.xml index 76b314e48aa4a440dc1f19f85558c27167fd8ffd..20c5909cc12ed3937cf5db1980e67cd8bd07aa6f 100755 --- a/apps/user_webdavauth/appinfo/info.xml +++ b/apps/user_webdavauth/appinfo/info.xml @@ -4,7 +4,7 @@ WebDAV user backend Authenticate users by a WebDAV call. You can use any WebDAV server, ownCloud server or other webserver to authenticate. It should return http 200 for right credentials and http 401 for wrong ones. - This app is not compatible to the LDAP user and group backend. + This app is not compatible with the LDAP user and group backend. AGPL Frank Karlitschek 4.93 diff --git a/apps/user_webdavauth/l10n/ast.php b/apps/user_webdavauth/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..118fa2ce30fd9b84b9a8eff32c0cc89fbb223318 --- /dev/null +++ b/apps/user_webdavauth/l10n/ast.php @@ -0,0 +1,7 @@ + "Autenticación per aciu de WevDAV", +"Address: " => "Direición:", +"The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials." => "Les credenciales d'usuariu van unviase a esta direición. Esti complementu verifica la rempuesta y va interpretar los códigos de rempuesta HTTP 401 y 403 como credenciales inválides y toles otres rempuestes como credenciales válides." +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_webdavauth/templates/settings.php b/apps/user_webdavauth/templates/settings.php index ad1701add8ca76c3bcadf356cf1d56439163d6d6..4596fdf3c78959d902cfc725e0830d111d4e5bf8 100755 --- a/apps/user_webdavauth/templates/settings.php +++ b/apps/user_webdavauth/templates/settings.php @@ -1,9 +1,7 @@ - -
-

t('WebDAV Authentication'));?>

-

- - -
t('The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials.')); ?> -

+ +

t('WebDAV Authentication'));?>

+

+ + +
t('The user credentials will be sent to this address. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials.')); ?>

diff --git a/autotest.sh b/autotest.sh index b88e9cf68b4c74829002e2bc54db7385b9d1c07b..4030fc0250e95bc2a42d2890cf251294c6307b4c 100755 --- a/autotest.sh +++ b/autotest.sh @@ -139,7 +139,7 @@ function execute_tests { cd $BASEDIR # revert changes to tests/data - git checkout tests/data/* + git checkout tests/data # reset data directory rm -rf $DATADIR diff --git a/build/package.json b/build/package.json index c9ed7b96c6c5b6af998c1f86a8a76f9bba4ea373..0c395839cf9cd00db2a12fd1dcfe4ec75330dbac 100644 --- a/build/package.json +++ b/build/package.json @@ -14,7 +14,9 @@ "karma": "*", "karma-jasmine": "*", "karma-junit-reporter": "*", - "karma-coverage": "*" + "karma-coverage": "*", + "karma-phantomjs-launcher": "*", + "phantomjs": "*" }, "engine": "node >= 0.8" } diff --git a/config/config.sample.php b/config/config.sample.php index 891c2eb5fa1fe92afe0539239abb8f964379e7ac..adcc175e2fae886746d80100523c33db232d115f 100755 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -41,7 +41,7 @@ $CONFIG = array( /* The automatic protocol detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the protocol detection. For example "https" */ "overwriteprotocol" => "", -/* The automatic webroot detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the automatic detection. For example "/domain.tld/ownCloud" */ +/* The automatic webroot detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the automatic detection. For example "/domain.tld/ownCloud". The value "/" can be used to remove the root. */ "overwritewebroot" => "", /* The automatic detection of ownCloud can fail in certain reverse proxy situations. This option allows to define a manually override condition as regular expression for the remote ip address. For example "^10\.0\.0\.[1-3]$" */ @@ -276,6 +276,15 @@ $CONFIG = array( /* all css and js files will be served by the web server statically in one js file and ons css file*/ 'asset-pipeline.enabled' => false, - /* where mount.json file should be stored, defaults to data/mount.json */ - 'mount_file' => '', +/* where mount.json file should be stored, defaults to data/mount.json */ +'mount_file' => '', + +/* + * Location of the cache folder, defaults to "data/$user/cache" where "$user" is the current user. + * + * When specified, the format will change to "$cache_path/$user" where "$cache_path" is the configured + * cache directory and "$user" is the user. + * + */ +'cache_path' => '' ); diff --git a/console.php b/console.php index 25b8b312539309e2c4ff8b4dcdb29d98602e7470..dd2c1026e477ef1d345062517204db0d712961db 100644 --- a/console.php +++ b/console.php @@ -8,7 +8,6 @@ use Symfony\Component\Console\Application; -$RUNTIME_NOAPPS = true; require_once 'lib/base.php'; // Don't do anything if ownCloud has not been installed yet @@ -22,6 +21,9 @@ if (!OC::$CLI) { exit(0); } +// load all apps to get all api routes properly setup +OC_App::loadApps(); + $defaults = new OC_Defaults; $application = new Application($defaults->getName(), \OC_Util::getVersionString()); require_once 'core/register_command.php'; diff --git a/core/ajax/share.php b/core/ajax/share.php index 3f04e1e4ad14691830b8f6d06ef6c7191aaa36b9..2b41bd8a5da17fb8693f50c658d3e6dd77db546b 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -21,7 +21,6 @@ OC_JSON::checkLoggedIn(); OCP\JSON::callCheck(); -OC_App::loadApps(); $defaults = new \OCP\Defaults(); @@ -206,6 +205,34 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo OC_JSON::success(array('data' => array('reshare' => $reshare, 'shares' => $shares))); } break; + case 'getShareWithEmail': + $result = array(); + if (isset($_GET['search'])) { + $cm = OC::$server->getContactsManager(); + if (!is_null($cm) && $cm->isEnabled()) { + $contacts = $cm->search($_GET['search'], array('FN', 'EMAIL')); + foreach ($contacts as $contact) { + if (!isset($contact['EMAIL'])) { + continue; + } + + $emails = $contact['EMAIL']; + if (!is_array($emails)) { + $emails = array($emails); + } + + foreach($emails as $email) { + $result[] = array( + 'id' => $contact['id'], + 'email' => $email, + 'displayname' => $contact['FN'], + ); + } + } + } + } + OC_JSON::success(array('data' => $result)); + break; case 'getShareWith': if (isset($_GET['search'])) { $sharePolicy = OC_Appconfig::getValue('core', 'shareapi_share_policy', 'global'); diff --git a/core/ajax/update.php b/core/ajax/update.php index 2a0cbb2036d6e59be5121e57abfc60942a169a6e..55e8ab15ec22800be2aee0787a990577b21e2269 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -1,6 +1,5 @@ getUserManager(); return $userManager->countUsers(); } @@ -56,4 +55,4 @@ class Report extends Command { $userDirectories = $dataview->getDirectoryContent('/', 'httpd/unix-directory'); return count($userDirectories); } -} \ No newline at end of file +} diff --git a/core/css/apps.css b/core/css/apps.css index 0e6a080c9cd7ebe1dfd3cf216d85952bc8f9aabe..a8dfc5b7ed12881a795c1a1e144cb715cb66e5dc 100644 --- a/core/css/apps.css +++ b/core/css/apps.css @@ -29,10 +29,14 @@ -moz-box-sizing: border-box; box-sizing: border-box; } #app-navigation .active, -#app-navigation .active a, -#app-navigation li:hover > a { +#app-navigation .active a { background-color: #ddd; } +#app-navigation li:hover > a, +#app-navigation .selected, +#app-navigation .selected a { + background-color: #ccc; +} /* special rules for first-level entries and folders */ #app-navigation > ul > li { @@ -151,9 +155,6 @@ transition: padding-bottom 500ms ease 0s; padding-bottom: 40px; } -#app-navigation .personalblock > legend { /* TODO @Raydiation: still needed? */ - padding: 10px 0; margin: 0; -} #app-navigation .error { color: #dd1144; } @@ -242,3 +243,24 @@ button.loading { padding-right: 30px; } + +/* general styles for the content area */ +.section { + display: block; + padding: 30px; + color: #555; + border-top: 1px solid #ddd; +} +.section h2 { + font-size: 20px; + margin-bottom: 7px; +} +.section h3 { + font-size: 16px; +} +/* slight position correction of checkboxes and radio buttons */ +.section input[type="checkbox"], +.section input[type="radio"] { + vertical-align: -2px; + margin-right: 4px; +} diff --git a/core/css/auth.css b/core/css/auth.css deleted file mode 100644 index 70df9f0ae0f886adbc8e3305693a3163b75515a8..0000000000000000000000000000000000000000 --- a/core/css/auth.css +++ /dev/null @@ -1,39 +0,0 @@ -h2 { - font-size:32px; - font-weight:700; - margin-bottom:16px; - white-space:nowrap; -} - -ul.scopes { - list-style:disc; -} - -ul.scopes li { - white-space:nowrap; -} - -h2 img { - width:50%; -} - -#oauth { - width:320px; - margin:64px auto 32px; -} - -#allow-auth { - background-color:#5c3; - box-shadow:0 1px 1px #fff, 0 1px 1px #5f3 inset; - color:#fff; - text-shadow:#5e3 0 1px 0; -} - -#deny-auth { - background:none; - border:0; - box-shadow:0 0 0 #fff, 0 0 0 #fff inset; - font-size:19px; - margin:11px; - padding:0; -} diff --git a/core/css/jquery.ocdialog.css b/core/css/jquery.ocdialog.css index 236968e3245b68e3ad7ba9138ec18c51aeac5be4..a1221137bc447da3394c3140d763f3ea35574dd7 100644 --- a/core/css/jquery.ocdialog.css +++ b/core/css/jquery.ocdialog.css @@ -43,7 +43,7 @@ background-color: #000; opacity: .20;filter:Alpha(Opacity=20); z-index: 999; - position: absolute; + position: fixed; top: 0; left: 0; width: 100%; height: 100%; } diff --git a/core/css/mobile.css b/core/css/mobile.css index a63aa902d347ce73850feac1a86ac1ac4e6b9522..c67ac3e5ecf82d3a3563c9ad2e7fade5593721f2 100644 --- a/core/css/mobile.css +++ b/core/css/mobile.css @@ -1,4 +1,12 @@ -@media only screen and (max-width: 600px) { +@media only screen and (max-width: 768px) { + +/* show caret indicator next to logo to make clear it is tappable */ +#owncloud.menutoggle { + background-image: url('../img/actions/caret.svg'); + background-repeat: no-repeat; + background-position: right 26px; + padding-right: 16px !important; +} /* compress search box on mobile, expand when focused */ .searchbox input[type="search"] { @@ -18,5 +26,80 @@ display: none; } +/* toggle navigation */ +#content-wrapper { + padding-left: 0; +} + +#navigation { + top: 45px; + bottom: initial; + width: 255px; + max-height: 90%; + margin-top: 0; + top: 45px; + background-color: rgba(36, 40, 47, .97); + overflow-x: initial; + border-bottom-right-radius: 7px; + border-bottom: 1px #333 solid; + border-right: 1px #333 solid; + box-shadow: 0 0 7px rgba(29,45,68,.97); + display: none; +} +#navigation, #navigation * { + box-sizing:border-box; -moz-box-sizing:border-box; +} +#navigation li { + display: inline-block; +} +#navigation a { + width: 80px; + height: 80px; + display: inline-block; + text-align: center; + padding: 20px 0; +} +#navigation a span { + display: inline-block; + font-size: 13px; + padding-bottom: 0; + padding-left: 0; + width: 80px; +} +#navigation .icon { + margin: 0 auto; + padding: 0; +} +#navigation li:first-child .icon { + padding-top: 0; +} +/* Apps management as sticky footer */ +#navigation .wrapper { + min-height: initial; + margin: 0; +} +#apps-management, #navigation .push { + height: initial; +} + + + +/* shift to account for missing navigation */ +#body-user #controls, +#body-settings #controls { + padding-left: 0; +} + +/* don’t require a minimum width for controls bar */ +#controls { + min-width: initial !important; +} + +/* position share dropdown */ +#dropdown { + margin-right: 10% !important; + width: 80% !important; +} + } diff --git a/core/css/styles.css b/core/css/styles.css index bd8111ebc725212f3f7331d17ffdd0e1e42a9347..57e2c4479a1c561e816ad1c1a60ca19309d78e10 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -77,6 +77,7 @@ body { background:#fefefe; font:normal .8em/1.6em "Helvetica Neue",Helvetica,Ari #header .logo { background-image: url(../img/logo.svg); + background-repeat: no-repeat; width: 250px; height: 118px; margin: 0 auto; @@ -84,6 +85,7 @@ body { background:#fefefe; font:normal .8em/1.6em "Helvetica Neue",Helvetica,Ari #header .logo-wide { background-image: url(../img/logo-wide.svg); + background-repeat: no-repeat; width: 147px; height: 32px; } @@ -99,11 +101,18 @@ input[type="time"], textarea, select, button, .button, +input[type="submit"], +input[type="button"], #quota, .pager li a { - width:10em; margin:.3em; padding:.6em .5em .4em; - font-size:1em; - background:#fff; color:#333; border:1px solid #ddd; outline:none; + width: 130px; + margin: 3px 3px 3px 0; + padding: 7px 6px 5px; + font-size: 13px; + background-color: #fff; + color: #333; + border: 1px solid #ddd; + outline: none; border-radius: 3px; } input[type="hidden"] { @@ -168,14 +177,12 @@ input[type="submit"], input[type="button"], button, .button, #quota, select, .pager li a { width: auto; - padding: .4em; + padding: 5px; background-color: rgba(240,240,240,.9); font-weight: bold; color: #555; border: 1px solid rgba(190,190,190,.9); cursor: pointer; - border-radius: 3px; - outline: none; } input[type="submit"]:hover, input[type="submit"]:focus, input[type="button"]:hover, input[type="button"]:focus, @@ -246,6 +253,7 @@ input[type="submit"].enabled { -webkit-box-sizing: border-box; box-sizing: border-box; position: fixed; + top:45px; right: 0; left: 0; height: 44px; @@ -275,6 +283,10 @@ input[type="submit"].enabled { padding: 7px 10px } +#controls .button.hidden { + display: none; +} + #content { position:relative; height:100%; width:100%; } #content .hascontrols { position: relative; @@ -790,20 +802,12 @@ tr .action { width:16px; height:16px; } tr:hover .action:hover, .selectedActions a:hover, .header-action:hover { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; } tbody tr:hover, tr:active { background-color:#f8f8f8; } -#body-settings h2 { - font-size: 20px; - font-weight: normal; - margin-bottom: 7px; -} -#body-settings .personalblock, #body-settings .helpblock { - padding: 30px; - color: #555; - border-top: 1px solid #ddd; -} -#body-settings .personalblock#quota { position:relative; padding:0; } -#body-settings #controls+.helpblock { position:relative; margin-top:3em; } code { font-family:"Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", monospace; } +#quota { + position: relative; + padding: 0; +} #quota div { padding: 0; background-color: rgb(220,220,220); @@ -922,6 +926,9 @@ div.crumb { background: url('../img/breadcrumb.svg') no-repeat right center; height: 44px; } +div.crumb.hidden { + display: none; +} div.crumb a, div.crumb span { position: relative; diff --git a/core/js/compatibility.js b/core/js/compatibility.js index 6548f95d42b348c6c77c06b9cd501d8da4580f6c..c07288857f27d5a45fa05049f29451466e852e5a 100644 --- a/core/js/compatibility.js +++ b/core/js/compatibility.js @@ -148,3 +148,7 @@ function outerHTML(node){ return h; })(node); } + +// devicePixelRatio for IE10 +window.devicePixelRatio = window.devicePixelRatio || + window.screen.deviceXDPI / window.screen.logicalXDPI || 1; diff --git a/core/js/core.json b/core/js/core.json index 665e2485a9042e2a46aecda61b3f76a4d6012bc4..05c2a17a679839dbb7e57fb7de2c322c18ef56de 100644 --- a/core/js/core.json +++ b/core/js/core.json @@ -6,7 +6,8 @@ "jquery-showpassword.js", "jquery.infieldlabel.js", "jquery.placeholder.js", - "jquery-tipsy.js" + "jquery-tipsy.js", + "underscore.js" ], "modules": [ "compatibility.js", diff --git a/core/js/jquery.avatar.js b/core/js/jquery.avatar.js index 381c42d9dbb5f816c0e0b8de992d481a603e72ce..7c19cb321fe7b5202868a7206598f7a9f3b75ec2 100644 --- a/core/js/jquery.avatar.js +++ b/core/js/jquery.avatar.js @@ -77,7 +77,7 @@ var url = OC.generateUrl( '/avatar/{user}/{size}?requesttoken={requesttoken}', - {user: user, size: size, requesttoken: oc_requesttoken}); + {user: user, size: size * window.devicePixelRatio, requesttoken: oc_requesttoken}); $.get(url, function(result) { if (typeof(result) === 'object') { @@ -93,9 +93,9 @@ } else { $div.show(); if (ie8fix === true) { - $div.html(''); + $div.html(''); } else { - $div.html(''); + $div.html(''); } } if(typeof callback === 'function') { diff --git a/core/js/js.js b/core/js/js.js index 3d3185f12c14ce2d4545dd0a9c0da3b9a6a54e51..f10c7163092cc2f5228aad706d23864611917a92 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -159,6 +159,7 @@ function escapeHTML(s) { * @param file The filename * @param dir The directory the file is in - e.g. $('#dir').val() * @return string +* @deprecated use Files.getDownloadURL() instead */ function fileDownloadPath(dir, file) { return OC.filePath('files', 'ajax', 'download.php')+'?files='+encodeURIComponent(file)+'&dir='+encodeURIComponent(dir); @@ -294,7 +295,7 @@ var OC={ */ imagePath:function(app,file){ if(file.indexOf('.')==-1){//if no extension is given, use png or svg depending on browser support - file+=(SVGSupport())?'.svg':'.png'; + file+=(OC.Util.hasSVGSupport())?'.svg':'.png'; } return OC.filePath(app,'img',file); }, @@ -371,6 +372,7 @@ var OC={ */ parseQueryString:function(queryString){ var parts, + pos, components, result = {}, key, @@ -378,12 +380,25 @@ var OC={ if (!queryString){ return null; } - if (queryString[0] === '?'){ - queryString = queryString.substr(1); + pos = queryString.indexOf('?'); + if (pos >= 0){ + queryString = queryString.substr(pos + 1); } - parts = queryString.split('&'); + parts = queryString.replace(/\+/g, '%20').split('&'); for (var i = 0; i < parts.length; i++){ - components = parts[i].split('='); + // split on first equal sign + var part = parts[i] + pos = part.indexOf('='); + if (pos >= 0) { + components = [ + part.substr(0, pos), + part.substr(pos + 1) + ] + } + else { + // key only + components = [part]; + } if (!components.length){ continue; } @@ -391,8 +406,14 @@ var OC={ if (!key){ continue; } - value = components[1]; - result[key] = value && decodeURIComponent(value); + // if equal sign was there, return string + if (components.length > 1) { + result[key] = decodeURIComponent(components[1]); + } + // no equal sign => null value + else { + result[key] = null; + } } return result; }, @@ -476,12 +497,59 @@ var OC={ throw e; }); } - if(!SVGSupport()) { - replaceSVG(); + if(!OC.Util.hasSVGSupport()) { + OC.Util.replaceSVG(); } }).show(); }, 'html'); } + }, + + // for menu toggling + registerMenu: function($toggle, $menuEl) { + $menuEl.addClass('menu'); + $toggle.addClass('menutoggle'); + $toggle.on('click.menu', function(event) { + if ($menuEl.is(OC._currentMenu)) { + $menuEl.hide(); + OC._currentMenu = null; + OC._currentMenuToggle = null; + return false; + } + // another menu was open? + else if (OC._currentMenu) { + // close it + OC._currentMenu.hide(); + } + $menuEl.show(); + OC._currentMenu = $menuEl; + OC._currentMenuToggle = $toggle; + return false + }); + }, + + unregisterMenu: function($toggle, $menuEl) { + // close menu if opened + if ($menuEl.is(OC._currentMenu)) { + $menuEl.hide(); + OC._currentMenu = null; + OC._currentMenuToggle = null; + } + $toggle.off('click.menu').removeClass('menutoggle'); + $menuEl.removeClass('menu'); + }, + + /** + * Wrapper for matchMedia + * + * This is makes it possible for unit tests to + * stub matchMedia (which doesn't work in PhantomJS) + */ + _matchMedia: function(media) { + if (window.matchMedia) { + return window.matchMedia(media); + } + return false; } }; OC.search.customResults={}; @@ -712,12 +780,12 @@ SVGSupport.checkMimeType=function(){ if(value[0]==='"'){ value=value.substr(1,value.length-2); } - headers[parts[0]]=value; + headers[parts[0].toLowerCase()]=value; } } }); - if(headers["Content-Type"]!=='image/svg+xml'){ - replaceSVG(); + if(headers["content-type"]!=='image/svg+xml'){ + OC.Util.replaceSVG(); SVGSupport.checkMimeType.correct=false; } } @@ -725,35 +793,10 @@ SVGSupport.checkMimeType=function(){ }; SVGSupport.checkMimeType.correct=true; -//replace all svg images with png for browser compatibility -function replaceSVG(){ - $('img.svg').each(function(index,element){ - element=$(element); - var src=element.attr('src'); - element.attr('src',src.substr(0,src.length-3)+'png'); - }); - $('.svg').each(function(index,element){ - element=$(element); - var background=element.css('background-image'); - if(background){ - var i=background.lastIndexOf('.svg'); - if(i>=0){ - background=background.substr(0,i)+'.png'+background.substr(i+4); - element.css('background-image',background); - } - } - element.find('*').each(function(index,element) { - element=$(element); - var background=element.css('background-image'); - if(background){ - var i=background.lastIndexOf('.svg'); - if(i>=0){ - background=background.substr(0,i)+'.png'+background.substr(i+4); - element.css('background-image',background); - } - } - }); - }); +// replace all svg images with png for browser compatibility +// @deprecated use OC.Util.replaceSVG instead +function replaceSVG($el){ + return OC.Util.replaceSVG($el); } /** @@ -831,8 +874,8 @@ function initCore() { initSessionHeartBeat(); } - if(!SVGSupport()){ //replace all svg images with png images for browser that dont support svg - replaceSVG(); + if(!OC.Util.hasSVGSupport()){ //replace all svg images with png images for browser that dont support svg + OC.Util.replaceSVG(); }else{ SVGSupport.checkMimeType(); } @@ -940,6 +983,67 @@ function initCore() { $('a.action').tipsy({gravity:'s', fade:true, live:true}); $('td .modified').tipsy({gravity:'s', fade:true, live:true}); $('input').tipsy({gravity:'w', fade:true}); + + // toggle for menus + $(document).on('mouseup.closemenus', function(event) { + var $el = $(event.target); + if ($el.closest('.menu').length || $el.closest('.menutoggle').length) { + // don't close when clicking on the menu directly or a menu toggle + return false; + } + if (OC._currentMenu) { + OC._currentMenu.hide(); + } + OC._currentMenu = null; + OC._currentMenuToggle = null; + }); + + + /** + * Set up the main menu toggle to react to media query changes. + * If the screen is small enough, the main menu becomes a toggle. + * If the screen is bigger, the main menu is not a toggle any more. + */ + function setupMainMenu() { + // toggle the navigation on mobile + if (!OC._matchMedia) { + return; + } + var mq = OC._matchMedia('(max-width: 768px)'); + var lastMatch = mq.matches; + var $toggle = $('#header #owncloud'); + var $navigation = $('#navigation'); + + function updateMainMenu() { + // mobile mode ? + if (lastMatch && !$toggle.hasClass('menutoggle')) { + // init the menu + OC.registerMenu($toggle, $navigation); + $toggle.data('oldhref', $toggle.attr('href')); + $toggle.attr('href', '#'); + $navigation.hide(); + } + else { + OC.unregisterMenu($toggle, $navigation); + $toggle.attr('href', $toggle.data('oldhref')); + $navigation.show(); + } + } + + updateMainMenu(); + + // TODO: debounce this + $(window).resize(function() { + if (lastMatch !== mq.matches) { + lastMatch = mq.matches; + updateMainMenu(); + } + }); + } + + if (window.matchMedia) { + setupMainMenu(); + } } $(document).ready(initCore); @@ -1005,6 +1109,72 @@ function relative_modified_date(timestamp) { else { return t('core','years ago'); } } +OC.Util = { + /** + * Returns whether the browser supports SVG + * + * @return true if the browser supports SVG, false otherwise + */ + // TODO: replace with original function + hasSVGSupport: SVGSupport, + /** + * If SVG is not supported, replaces the given icon's extension + * from ".svg" to ".png". + * If SVG is supported, return the image path as is. + * + * @param file image path with svg extension + * @return fixed image path with png extension if SVG is not + * supported + */ + replaceSVGIcon: function(file) { + if (!OC.Util.hasSVGSupport()) { + var i = file.lastIndexOf('.svg'); + if (i >= 0) { + file = file.substr(0, i) + '.png' + file.substr(i+4); + } + } + return file; + }, + /** + * Replace SVG images in all elements that have the "svg" class set + * with PNG images. + * + * @param $el root element from which to search, defaults to $('body') + */ + replaceSVG: function($el) { + if (!$el) { + $el = $('body'); + } + $el.find('img.svg').each(function(index,element){ + element=$(element); + var src=element.attr('src'); + element.attr('src',src.substr(0, src.length-3) + 'png'); + }); + $el.find('.svg').each(function(index,element){ + element = $(element); + var background = element.css('background-image'); + if (background){ + var i = background.lastIndexOf('.svg'); + if (i >= 0){ + background = background.substr(0,i) + '.png' + background.substr(i + 4); + element.css('background-image', background); + } + } + element.find('*').each(function(index, element) { + element = $(element); + var background = element.css('background-image'); + if (background) { + var i = background.lastIndexOf('.svg'); + if(i >= 0){ + background = background.substr(0,i) + '.png' + background.substr(i + 4); + element.css('background-image', background); + } + } + }); + }); + } +}; + /** * get a variable by name * @param string name diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index d1bcb4659b89c80671aa65578d40e51b66789458..11833f12e2d108118533aa5fbf88c6edfda475a2 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -19,6 +19,8 @@ * */ +/* global OC, t, alert */ + /** * this class to ease the usage of jquery dialogs */ @@ -27,7 +29,7 @@ var OCdialogs = { YES_NO_BUTTONS: 70, OK_BUTTONS: 71, // used to name each dialog - dialogs_counter: 0, + dialogsCounter: 0, /** * displays alert dialog * @param text content of dialog @@ -52,7 +54,8 @@ var OCdialogs = { * displays confirmation dialog * @param text content of dialog * @param title dialog title - * @param callback which will be triggered when user presses YES or NO (true or false would be passed to callback respectively) + * @param callback which will be triggered when user presses YES or NO + * (true or false would be passed to callback respectively) * @param modal make the dialog modal */ confirm:function(text, title, callback, modal) { @@ -63,21 +66,20 @@ var OCdialogs = { * @param title dialog title * @param callback which will be triggered when user presses Choose * @param multiselect whether it should be possible to select multiple files - * @param mimetype_filter mimetype to filter by + * @param mimetypeFilter mimetype to filter by * @param modal make the dialog modal */ - filepicker:function(title, callback, multiselect, mimetype_filter, modal) { + filepicker:function(title, callback, multiselect, mimetypeFilter, modal) { var self = this; $.when(this._getFilePickerTemplate()).then(function($tmpl) { - var dialog_name = 'oc-dialog-filepicker-content'; - var dialog_id = '#' + dialog_name; + var dialogName = 'oc-dialog-filepicker-content'; if(self.$filePicker) { self.$filePicker.ocdialog('close'); } self.$filePicker = $tmpl.octemplate({ - dialog_name: dialog_name, + dialog_name: dialogName, title: title - }).data('path', '').data('multiselect', multiselect).data('mimetype', mimetype_filter); + }).data('path', '').data('multiselect', multiselect).data('mimetype', mimetypeFilter); if (modal === undefined) { modal = false; @@ -85,8 +87,8 @@ var OCdialogs = { if (multiselect === undefined) { multiselect = false; } - if (mimetype_filter === undefined) { - mimetype_filter = ''; + if (mimetypeFilter === undefined) { + mimetypeFilter = ''; } $('body').append(self.$filePicker); @@ -131,13 +133,16 @@ var OCdialogs = { height: 420, modal: modal, buttons: buttonlist, - close: function(event, ui) { + close: function() { try { $(this).ocdialog('destroy').remove(); } catch(e) {} self.$filePicker = null; } }); + if (!OC.Util.hasSVGSupport()) { + OC.Util.replaceSVG(self.$filePicker.parent()); + } }) .fail(function(status, error) { // If the method is called while navigating away @@ -151,15 +156,15 @@ var OCdialogs = { * Displays raw dialog * You better use a wrapper instead ... */ - message:function(content, title, dialog_type, buttons, callback, modal) { + message:function(content, title, dialogType, buttons, callback, modal) { $.when(this._getMessageTemplate()).then(function($tmpl) { - var dialog_name = 'oc-dialog-' + OCdialogs.dialogs_counter + '-content'; - var dialog_id = '#' + dialog_name; + var dialogName = 'oc-dialog-' + OCdialogs.dialogsCounter + '-content'; + var dialogId = '#' + dialogName; var $dlg = $tmpl.octemplate({ - dialog_name: dialog_name, + dialog_name: dialogName, title: title, message: content, - type: dialog_type + type: dialogType }); if (modal === undefined) { modal = false; @@ -167,48 +172,48 @@ var OCdialogs = { $('body').append($dlg); var buttonlist = []; switch (buttons) { - case OCdialogs.YES_NO_BUTTONS: - buttonlist = [{ - text: t('core', 'Yes'), - click: function(){ - if (callback !== undefined) { - callback(true); - } - $(dialog_id).ocdialog('close'); - }, - defaultButton: true + case OCdialogs.YES_NO_BUTTONS: + buttonlist = [{ + text: t('core', 'Yes'), + click: function(){ + if (callback !== undefined) { + callback(true); + } + $(dialogId).ocdialog('close'); }, - { - text: t('core', 'No'), - click: function(){ - if (callback !== undefined) { - callback(false); - } - $(dialog_id).ocdialog('close'); + defaultButton: true + }, + { + text: t('core', 'No'), + click: function(){ + if (callback !== undefined) { + callback(false); } - }]; + $(dialogId).ocdialog('close'); + } + }]; break; - case OCdialogs.OK_BUTTON: - var functionToCall = function() { - $(dialog_id).ocdialog('close'); - if(callback !== undefined) { - callback(); - } - }; - buttonlist[0] = { - text: t('core', 'Ok'), - click: functionToCall, - defaultButton: true - }; + case OCdialogs.OK_BUTTON: + var functionToCall = function() { + $(dialogId).ocdialog('close'); + if(callback !== undefined) { + callback(); + } + }; + buttonlist[0] = { + text: t('core', 'Ok'), + click: functionToCall, + defaultButton: true + }; break; } - $(dialog_id).ocdialog({ + $(dialogId).ocdialog({ closeOnEscape: true, modal: modal, buttons: buttonlist }); - OCdialogs.dialogs_counter++; + OCdialogs.dialogsCounter++; }) .fail(function(status, error) { // If the method is called while navigating away from @@ -246,7 +251,7 @@ var OCdialogs = { image.onload = function () { var url = crop(image); deferred.resolve(url); - } + }; }; reader.readAsArrayBuffer(file); } else { @@ -294,7 +299,7 @@ var OCdialogs = { conflict.find('.replacement .mtime').text(formatDate(replacement.lastModifiedDate)); } var path = original.directory + '/' +original.name; - Files.lazyLoadPreview(path, original.mime, function(previewpath){ + Files.lazyLoadPreview(path, original.mimetype, function(previewpath){ conflict.find('.original .icon').css('background-image','url('+previewpath+')'); }, 96, 96, original.etag); getCroppedPreview(replacement).then( @@ -334,129 +339,133 @@ var OCdialogs = { //if (selection.defaultAction) { // controller[selection.defaultAction](data); //} else { - var dialog_name = 'oc-dialog-fileexists-content'; - var dialog_id = '#' + dialog_name; - if (this._fileexistsshown) { - // add conflict - - var conflicts = $(dialog_id+ ' .conflicts'); - addConflict(conflicts, original, replacement); + var dialogName = 'oc-dialog-fileexists-content'; + var dialogId = '#' + dialogName; + if (this._fileexistsshown) { + // add conflict + + var conflicts = $(dialogId+ ' .conflicts'); + addConflict(conflicts, original, replacement); + + var count = $(dialogId+ ' .conflict').length; + var title = n('core', + '{count} file conflict', + '{count} file conflicts', + count, + {count:count} + ); + $(dialogId).parent().children('.oc-dialog-title').text(title); + + //recalculate dimensions + $(window).trigger('resize'); - var count = $(dialog_id+ ' .conflict').length; - var title = n('files', - '{count} file conflict', - '{count} file conflicts', - count, - {count:count} - ); - $(dialog_id).parent().children('.oc-dialog-title').text(title); + } else { + //create dialog + this._fileexistsshown = true; + $.when(this._getFileExistsTemplate()).then(function($tmpl) { + var title = t('core','One file conflict'); + var $dlg = $tmpl.octemplate({ + dialog_name: dialogName, + title: title, + type: 'fileexists', + + allnewfiles: t('core','New Files'), + allexistingfiles: t('core','Already existing files'), + + why: t('core','Which files do you want to keep?'), + what: t('core','If you select both versions, the copied file will have a number added to its name.') + }); + $('body').append($dlg); - //recalculate dimensions - $(window).trigger('resize'); + var conflicts = $($dlg).find('.conflicts'); + addConflict(conflicts, original, replacement); - } else { - //create dialog - this._fileexistsshown = true; - $.when(this._getFileExistsTemplate()).then(function($tmpl) { - var title = t('files','One file conflict'); - var $dlg = $tmpl.octemplate({ - dialog_name: dialog_name, - title: title, - type: 'fileexists', - - why: t('files','Which files do you want to keep?'), - what: t('files','If you select both versions, the copied file will have a number added to its name.') - }); - $('body').append($dlg); - - var conflicts = $($dlg).find('.conflicts'); - addConflict(conflicts, original, replacement); - - buttonlist = [{ - text: t('core', 'Cancel'), - classes: 'cancel', - click: function(){ - if ( typeof controller.onCancel !== 'undefined') { - controller.onCancel(data); - } - $(dialog_id).ocdialog('close'); + var buttonlist = [{ + text: t('core', 'Cancel'), + classes: 'cancel', + click: function(){ + if ( typeof controller.onCancel !== 'undefined') { + controller.onCancel(data); } - }, - { - text: t('core', 'Continue'), - classes: 'continue', - click: function(){ - if ( typeof controller.onContinue !== 'undefined') { - controller.onContinue($(dialog_id + ' .conflict')); - } - $(dialog_id).ocdialog('close'); + $(dialogId).ocdialog('close'); + } + }, + { + text: t('core', 'Continue'), + classes: 'continue', + click: function(){ + if ( typeof controller.onContinue !== 'undefined') { + controller.onContinue($(dialogId + ' .conflict')); } - }]; - - $(dialog_id).ocdialog({ - width: 500, - closeOnEscape: true, - modal: true, - buttons: buttonlist, - closeButton: null, - close: function(event, ui) { - self._fileexistsshown = false; + $(dialogId).ocdialog('close'); + } + }]; + + $(dialogId).ocdialog({ + width: 500, + closeOnEscape: true, + modal: true, + buttons: buttonlist, + closeButton: null, + close: function() { + self._fileexistsshown = false; $(this).ocdialog('destroy').remove(); } - }); + }); - $(dialog_id).css('height','auto'); + $(dialogId).css('height','auto'); - //add checkbox toggling actions - $(dialog_id).find('.allnewfiles').on('click', function() { - var checkboxes = $(dialog_id).find('.conflict .replacement input[type="checkbox"]'); - checkboxes.prop('checked', $(this).prop('checked')); - }); - $(dialog_id).find('.allexistingfiles').on('click', function() { - var checkboxes = $(dialog_id).find('.conflict .original input[type="checkbox"]'); - checkboxes.prop('checked', $(this).prop('checked')); - }); - $(dialog_id).find('.conflicts').on('click', '.replacement,.original', function() { - var checkbox = $(this).find('input[type="checkbox"]'); - checkbox.prop('checked', !checkbox.prop('checked')); - }); - $(dialog_id).find('.conflicts').on('click', 'input[type="checkbox"]', function() { - var checkbox = $(this); - checkbox.prop('checked', !checkbox.prop('checked')); - }); + //add checkbox toggling actions + $(dialogId).find('.allnewfiles').on('click', function() { + var checkboxes = $(dialogId).find('.conflict .replacement input[type="checkbox"]'); + checkboxes.prop('checked', $(this).prop('checked')); + }); + $(dialogId).find('.allexistingfiles').on('click', function() { + var checkboxes = $(dialogId).find('.conflict .original input[type="checkbox"]'); + checkboxes.prop('checked', $(this).prop('checked')); + }); + $(dialogId).find('.conflicts').on('click', '.replacement,.original', function() { + var checkbox = $(this).find('input[type="checkbox"]'); + checkbox.prop('checked', !checkbox.prop('checked')); + }); + $(dialogId).find('.conflicts').on('click', 'input[type="checkbox"]', function() { + var checkbox = $(this); + checkbox.prop('checked', !checkbox.prop('checked')); + }); - //update counters - $(dialog_id).on('click', '.replacement,.allnewfiles', function() { - var count = $(dialog_id).find('.conflict .replacement input[type="checkbox"]:checked').length; - if (count === $(dialog_id+ ' .conflict').length) { - $(dialog_id).find('.allnewfiles').prop('checked', true); - $(dialog_id).find('.allnewfiles + .count').text(t('files','(all selected)')); - } else if (count > 0) { - $(dialog_id).find('.allnewfiles').prop('checked', false); - $(dialog_id).find('.allnewfiles + .count').text(t('files','({count} selected)',{count:count})); - } else { - $(dialog_id).find('.allnewfiles').prop('checked', false); - $(dialog_id).find('.allnewfiles + .count').text(''); - } - }); - $(dialog_id).on('click', '.original,.allexistingfiles', function(){ - var count = $(dialog_id).find('.conflict .original input[type="checkbox"]:checked').length; - if (count === $(dialog_id+ ' .conflict').length) { - $(dialog_id).find('.allexistingfiles').prop('checked', true); - $(dialog_id).find('.allexistingfiles + .count').text(t('files','(all selected)')); - } else if (count > 0) { - $(dialog_id).find('.allexistingfiles').prop('checked', false); - $(dialog_id).find('.allexistingfiles + .count').text(t('files','({count} selected)',{count:count})); - } else { - $(dialog_id).find('.allexistingfiles').prop('checked', false); - $(dialog_id).find('.allexistingfiles + .count').text(''); - } - }); - }) - .fail(function() { - alert(t('core', 'Error loading file exists template')); + //update counters + $(dialogId).on('click', '.replacement,.allnewfiles', function() { + var count = $(dialogId).find('.conflict .replacement input[type="checkbox"]:checked').length; + if (count === $(dialogId+ ' .conflict').length) { + $(dialogId).find('.allnewfiles').prop('checked', true); + $(dialogId).find('.allnewfiles + .count').text(t('core','(all selected)')); + } else if (count > 0) { + $(dialogId).find('.allnewfiles').prop('checked', false); + $(dialogId).find('.allnewfiles + .count').text(t('core','({count} selected)',{count:count})); + } else { + $(dialogId).find('.allnewfiles').prop('checked', false); + $(dialogId).find('.allnewfiles + .count').text(''); + } }); - } + $(dialogId).on('click', '.original,.allexistingfiles', function(){ + var count = $(dialogId).find('.conflict .original input[type="checkbox"]:checked').length; + if (count === $(dialogId+ ' .conflict').length) { + $(dialogId).find('.allexistingfiles').prop('checked', true); + $(dialogId).find('.allexistingfiles + .count').text(t('core','(all selected)')); + } else if (count > 0) { + $(dialogId).find('.allexistingfiles').prop('checked', false); + $(dialogId).find('.allexistingfiles + .count') + .text(t('core','({count} selected)',{count:count})); + } else { + $(dialogId).find('.allexistingfiles').prop('checked', false); + $(dialogId).find('.allexistingfiles + .count').text(''); + } + }); + }) + .fail(function() { + alert(t('core', 'Error loading file exists template')); + }); + } //} }, _getFilePickerTemplate: function() { @@ -514,20 +523,13 @@ var OCdialogs = { } return $.getJSON( - OC.filePath('files', 'ajax', 'rawlist.php'), + OC.filePath('files', 'ajax', 'list.php'), { dir: dir, mimetypes: JSON.stringify(mimeType) } ); }, - _determineValue: function(element) { - if ( $(element).attr('type') === 'checkbox' ) { - return element.checked; - } else { - return $(element).val(); - } - }, /** * fills the filepicker with files @@ -539,7 +541,7 @@ var OCdialogs = { this.$filelist.empty().addClass('loading'); this.$filePicker.data('path', dir); $.when(this._getFileList(dir, this.$filePicker.data('mimetype'))).then(function(response) { - $.each(response.data, function(index, file) { + $.each(response.data.files, function(index, file) { if (file.type === 'dir') { dirs.push(file); } else { @@ -555,13 +557,25 @@ var OCdialogs = { type: entry.type, dir: dir, filename: entry.name, - date: OC.mtime2date(entry.mtime) + date: OC.mtime2date(Math.floor(entry.mtime / 1000)) }); - $li.find('img').attr('src', entry.mimetype_icon); + if (entry.isPreviewAvailable) { + var urlSpec = { + file: dir + '/' + entry.name + }; + var previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec); + $li.find('img').attr('src', previewUrl); + } + else { + $li.find('img').attr('src', OC.Util.replaceSVGIcon(entry.icon)); + } self.$filelist.append($li); }); self.$filelist.removeClass('loading'); + if (!OC.Util.hasSVGSupport()) { + OC.Util.replaceSVG(self.$filePicker.find('.dirtree')); + } }); }, /** @@ -607,7 +621,6 @@ var OCdialogs = { this.$filelist.find('.filepicker_element_selected').removeClass('filepicker_element_selected'); } $element.toggleClass('filepicker_element_selected'); - return; } else if ( $element.data('type') === 'dir' ) { this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname')); } diff --git a/core/js/share.js b/core/js/share.js index 9ee50ff6963473b11e6d1683dd340565f76d2cfc..5cabc6145634e94b32c6ea6ae60135ebcc71aa03 100644 --- a/core/js/share.js +++ b/core/js/share.js @@ -48,7 +48,7 @@ OC.Share={ var action = $(file).find('.fileactions .action[data-action="Share"]'); var img = action.find('img').attr('src', image); action.addClass('permanent'); - action.html(' '+t('core', 'Shared')).prepend(img); + action.html(' '+t('core', 'Shared')+'').prepend(img); } else { var dir = $('#dir').val(); if (dir.length > 1) { @@ -63,7 +63,7 @@ OC.Share={ if (img.attr('src') != OC.imagePath('core', 'actions/public')) { img.attr('src', image); $(action).addClass('permanent'); - $(action).html(' '+t('core', 'Shared')).prepend(img); + $(action).html(' '+t('core', 'Shared')+'').prepend(img); } }); } @@ -103,10 +103,10 @@ OC.Share={ var img = action.find('img').attr('src', image); if (shares) { action.addClass('permanent'); - action.html(' '+ escapeHTML(t('core', 'Shared'))).prepend(img); + action.html(' '+ escapeHTML(t('core', 'Shared'))+'').prepend(img); } else { action.removeClass('permanent'); - action.html(' '+ escapeHTML(t('core', 'Share'))).prepend(img); + action.html(' '+ escapeHTML(t('core', 'Share'))+'').prepend(img); } } } @@ -331,6 +331,26 @@ OC.Share={ .append( insert ) .appendTo( ul ); }; + $('#email').autocomplete({ + minLength: 1, + source: function (search, response) { + $.get(OC.filePath('core', 'ajax', 'share.php'), { fetch: 'getShareWithEmail', search: search.term }, function(result) { + if (result.status == 'success' && result.data.length > 0) { + response(result.data); + } + }); + }, + select: function( event, item ) { + $('#email').val(item.item.email); + return false; + } + }) + .data("ui-autocomplete")._renderItem = function( ul, item ) { + return $( "
  • " ) + .append( "" + item.displayname + "
    " + item.email + "
    " ) + .appendTo( ul ); + }; + } else { html += ''; html += '
  • '; @@ -551,7 +571,7 @@ $(document).ready(function() { var itemType = $('#dropdown').data('item-type'); var itemSource = $('#dropdown').data('item-source'); var shareType = $li.data('share-type'); - var shareWith = $li.data('share-with'); + var shareWith = $li.attr('data-share-with'); OC.Share.unshare(itemType, itemSource, shareType, shareWith, function() { $li.remove(); var index = OC.Share.itemShares[shareType].indexOf(shareWith); @@ -597,7 +617,7 @@ $(document).ready(function() { OC.Share.setPermissions($('#dropdown').data('item-type'), $('#dropdown').data('item-source'), li.data('share-type'), - li.data('share-with'), + li.attr('data-share-with'), permissions); }); @@ -782,7 +802,7 @@ $(document).ready(function() { } var shareType = $li.data('share-type'); - var shareWith = $li.data('share-with'); + var shareWith = $li.attr('data-share-with'); $.post(OC.filePath('core', 'ajax', 'share.php'), {action: action, recipient: shareWith, shareType: shareType, itemSource: itemSource, itemType: itemType}, function(result) { if (result.status !== 'success') { diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js index 069546387c71c23483c7db84ff3b1f2c41a51263..ccd9f7a128898003adb606154b2d88a028ce3724 100644 --- a/core/js/tests/specs/coreSpec.js +++ b/core/js/tests/specs/coreSpec.js @@ -147,19 +147,19 @@ describe('Core base tests', function() { }); describe('Images', function() { it('Generates image path with given extension', function() { - var svgSupportStub = sinon.stub(window, 'SVGSupport', function() { return true; }); + var svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport', function() { return true; }); expect(OC.imagePath('core', 'somefile.jpg')).toEqual(OC.webroot + '/core/img/somefile.jpg'); expect(OC.imagePath(TESTAPP, 'somefile.jpg')).toEqual(TESTAPP_ROOT + '/img/somefile.jpg'); svgSupportStub.restore(); }); it('Generates image path with svg extension when svg support exists', function() { - var svgSupportStub = sinon.stub(window, 'SVGSupport', function() { return true; }); + var svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport', function() { return true; }); expect(OC.imagePath('core', 'somefile')).toEqual(OC.webroot + '/core/img/somefile.svg'); expect(OC.imagePath(TESTAPP, 'somefile')).toEqual(TESTAPP_ROOT + '/img/somefile.svg'); svgSupportStub.restore(); }); it('Generates image path with png ext when svg support is not available', function() { - var svgSupportStub = sinon.stub(window, 'SVGSupport', function() { return false; }); + var svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport', function() { return false; }); expect(OC.imagePath('core', 'somefile')).toEqual(OC.webroot + '/core/img/somefile.png'); expect(OC.imagePath(TESTAPP, 'somefile')).toEqual(TESTAPP_ROOT + '/img/somefile.png'); svgSupportStub.restore(); @@ -268,7 +268,72 @@ describe('Core base tests', function() { // still nothing expect(counter).toEqual(0); }); - + }); + describe('Parse query string', function() { + it('Parses query string from full URL', function() { + var query = OC.parseQueryString('http://localhost/stuff.php?q=a&b=x'); + expect(query).toEqual({q: 'a', b: 'x'}); + }); + it('Parses query string from query part alone', function() { + var query = OC.parseQueryString('q=a&b=x'); + expect(query).toEqual({q: 'a', b: 'x'}); + }); + it('Returns null hash when empty query', function() { + var query = OC.parseQueryString(''); + expect(query).toEqual(null); + }); + it('Returns empty hash when empty query with question mark', function() { + var query = OC.parseQueryString('?'); + expect(query).toEqual({}); + }); + it('Decodes regular query strings', function() { + var query = OC.parseQueryString('a=abc&b=def'); + expect(query).toEqual({ + a: 'abc', + b: 'def' + }); + }); + it('Ignores empty parts', function() { + var query = OC.parseQueryString('&q=a&&b=x&'); + expect(query).toEqual({q: 'a', b: 'x'}); + }); + it('Ignores lone equal signs', function() { + var query = OC.parseQueryString('&q=a&=&b=x&'); + expect(query).toEqual({q: 'a', b: 'x'}); + }); + it('Includes extra equal signs in value', function() { + var query = OC.parseQueryString('u=a=x&q=a=b'); + expect(query).toEqual({u: 'a=x', q: 'a=b'}); + }); + it('Decodes plus as space', function() { + var query = OC.parseQueryString('space+key=space+value'); + expect(query).toEqual({'space key': 'space value'}); + }); + it('Decodes special characters', function() { + var query = OC.parseQueryString('unicode=%E6%B1%89%E5%AD%97'); + expect(query).toEqual({unicode: '汉字'}); + query = OC.parseQueryString('b=spaace%20value&space%20key=normalvalue&slash%2Fthis=amp%26ersand'); + expect(query).toEqual({ + b: 'spaace value', + 'space key': 'normalvalue', + 'slash/this': 'amp&ersand' + }); + }); + it('Decodes empty values', function() { + var query = OC.parseQueryString('keywithemptystring=&keywithnostring'); + expect(query).toEqual({ + 'keywithemptystring': '', + 'keywithnostring': null + }); + }); + it('Does not interpret data types', function() { + var query = OC.parseQueryString('booleanfalse=false&booleantrue=true&number=123'); + expect(query).toEqual({ + 'booleanfalse': 'false', + 'booleantrue': 'true', + 'number': '123' + }); + }); }); describe('Generate Url', function() { it('returns absolute urls', function() { @@ -279,5 +344,135 @@ describe('Core base tests', function() { expect(OC.generateUrl('apps/files/download{file}', {file: '/Welcome.txt'})).toEqual(OC.webroot + '/index.php/apps/files/download/Welcome.txt'); }); }); + describe('Main menu mobile toggle', function() { + var oldMatchMedia; + var $toggle; + var $navigation; + + beforeEach(function() { + oldMatchMedia = OC._matchMedia; + // a separate method was needed because window.matchMedia + // cannot be stubbed due to a bug in PhantomJS: + // https://github.com/ariya/phantomjs/issues/12069 + OC._matchMedia = sinon.stub(); + $('#testArea').append('' + + ''); + $toggle = $('#owncloud'); + $navigation = $('#navigation'); + }); + + afterEach(function() { + OC._matchMedia = oldMatchMedia; + }); + it('Sets up menu toggle in mobile mode', function() { + OC._matchMedia.returns({matches: true}); + window.initCore(); + expect($toggle.hasClass('menutoggle')).toEqual(true); + expect($navigation.hasClass('menu')).toEqual(true); + }); + it('Does not set up menu toggle in desktop mode', function() { + OC._matchMedia.returns({matches: false}); + window.initCore(); + expect($toggle.hasClass('menutoggle')).toEqual(false); + expect($navigation.hasClass('menu')).toEqual(false); + }); + it('Switches on menu toggle when mobile mode changes', function() { + var mq = {matches: false}; + OC._matchMedia.returns(mq); + window.initCore(); + expect($toggle.hasClass('menutoggle')).toEqual(false); + mq.matches = true; + $(window).trigger('resize'); + expect($toggle.hasClass('menutoggle')).toEqual(true); + }); + it('Switches off menu toggle when mobile mode changes', function() { + var mq = {matches: true}; + OC._matchMedia.returns(mq); + window.initCore(); + expect($toggle.hasClass('menutoggle')).toEqual(true); + mq.matches = false; + $(window).trigger('resize'); + expect($toggle.hasClass('menutoggle')).toEqual(false); + }); + it('Clicking menu toggle toggles navigation in mobile mode', function() { + OC._matchMedia.returns({matches: true}); + window.initCore(); + $navigation.hide(); // normally done through media query triggered CSS + expect($navigation.is(':visible')).toEqual(false); + $toggle.click(); + expect($navigation.is(':visible')).toEqual(true); + $toggle.click(); + expect($navigation.is(':visible')).toEqual(false); + }); + it('Clicking menu toggle does not toggle navigation in desktop mode', function() { + OC._matchMedia.returns({matches: false}); + window.initCore(); + expect($navigation.is(':visible')).toEqual(true); + $toggle.click(); + expect($navigation.is(':visible')).toEqual(true); + }); + it('Switching to mobile mode hides navigation', function() { + var mq = {matches: false}; + OC._matchMedia.returns(mq); + window.initCore(); + expect($navigation.is(':visible')).toEqual(true); + mq.matches = true; + $(window).trigger('resize'); + expect($navigation.is(':visible')).toEqual(false); + }); + it('Switching to desktop mode shows navigation', function() { + var mq = {matches: true}; + OC._matchMedia.returns(mq); + window.initCore(); + expect($navigation.is(':visible')).toEqual(false); + mq.matches = false; + $(window).trigger('resize'); + expect($navigation.is(':visible')).toEqual(true); + }); + it('Switch to desktop with opened menu then back to mobile resets toggle', function() { + var mq = {matches: true}; + OC._matchMedia.returns(mq); + window.initCore(); + expect($navigation.is(':visible')).toEqual(false); + $toggle.click(); + expect($navigation.is(':visible')).toEqual(true); + mq.matches = false; + $(window).trigger('resize'); + expect($navigation.is(':visible')).toEqual(true); + mq.matches = true; + $(window).trigger('resize'); + expect($navigation.is(':visible')).toEqual(false); + $toggle.click(); + expect($navigation.is(':visible')).toEqual(true); + }); + }); + describe('SVG extension replacement', function() { + var svgSupportStub; + + beforeEach(function() { + svgSupportStub = sinon.stub(OC.Util, 'hasSVGSupport'); + }); + afterEach(function() { + svgSupportStub.restore(); + }); + it('does not replace svg extension with png when SVG is supported', function() { + svgSupportStub.returns(true); + expect( + OC.Util.replaceSVGIcon('/path/to/myicon.svg?someargs=1') + ).toEqual( + '/path/to/myicon.svg?someargs=1' + ); + }); + it('replaces svg extension with png when SVG not supported', function() { + svgSupportStub.returns(false); + expect( + OC.Util.replaceSVGIcon('/path/to/myicon.svg?someargs=1') + ).toEqual( + '/path/to/myicon.png?someargs=1' + ); + }); + }); }); diff --git a/core/js/underscore.js b/core/js/underscore.js new file mode 100644 index 0000000000000000000000000000000000000000..ca61fdc3a4bab9ae3cc46d53802772dc4621ea37 --- /dev/null +++ b/core/js/underscore.js @@ -0,0 +1,1344 @@ +// Underscore.js 1.6.0 +// http://underscorejs.org +// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.6.0'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return obj; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, length = obj.length; i < length; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; + } + } + return obj; + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var result; + any(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); + each(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, function(value, index, list) { + return !predicate.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); + each(obj, function(value, index, list) { + if (!(result = result && predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); + each(obj, function(value, index, list) { + if (result || (result = predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matches(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matches(attrs)); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + var result = -Infinity, lastComputed = -Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed > lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + var result = Infinity, lastComputed = Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed < lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Shuffle an array, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (obj.length !== +obj.length) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + if (value == null) return _.identity; + if (_.isFunction(value)) return value; + return _.property(value); + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + iterator = lookupIterator(iterator); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iterator, context) { + var result = {}; + iterator = lookupIterator(iterator); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, key, value) { + _.has(result, key) ? result[key].push(value) : result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, key, value) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, key) { + _.has(result, key) ? result[key]++ : result[key] = 1; + }); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[0]; + if (n < 0) return []; + return slice.call(array, 0, n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[array.length - 1]; + return slice.call(array, Math.max(array.length - n, 0)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Split an array into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(array, predicate, context) { + predicate = lookupIterator(predicate); + var pass = [], fail = []; + each(array, function(elem) { + (predicate.call(context, elem) ? pass : fail).push(elem); + }); + return [pass, fail]; + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.contains(other, item); + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var length = _.max(_.pluck(arguments, 'length').concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(length); + + while(idx < length) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + return function() { + var position = 0; + var args = boundArgs.slice(); + for (var i = 0, length = args.length; i < length; i++) { + if (args[i] === _) args[i] = arguments[position++]; + } + while (position < arguments.length) args.push(arguments[position++]); + return func.apply(this, args); + }; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error('bindAll must be passed function names'); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = new Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = new Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor)) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + _.constant = function(value) { + return function () { + return value; + }; + }; + + _.property = function(key) { + return function(obj) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of `key:value` pairs. + _.matches = function(attrs) { + return function(obj) { + if (obj === attrs) return true; //avoid comparing an object to itself. + for (var key in attrs) { + if (attrs[key] !== obj[key]) + return false; + } + return true; + } + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { return new Date().getTime(); }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}).call(this); diff --git a/core/l10n/ast.php b/core/l10n/ast.php new file mode 100644 index 0000000000000000000000000000000000000000..0fcda328dc0c98e72b958bf8ee850c1a351c5b35 --- /dev/null +++ b/core/l10n/ast.php @@ -0,0 +1,77 @@ + "Base de datos anovada", +"Invalid image" => "Imaxe inválida", +"Sunday" => "Domingu", +"Monday" => "Llunes", +"Tuesday" => "Martes", +"Wednesday" => "Miércoles", +"Thursday" => "Xueves", +"Friday" => "Vienres", +"Saturday" => "Sábadu", +"January" => "Xineru", +"February" => "Febreru", +"March" => "Marzu", +"April" => "Abril", +"May" => "Mayu", +"June" => "Xunu", +"July" => "Xunetu", +"August" => "Agostu", +"September" => "Setiembre", +"October" => "Ochobre", +"November" => "Payares", +"December" => "Avientu", +"Settings" => "Axustes", +"seconds ago" => "fai segundos", +"_%n minute ago_::_%n minutes ago_" => array("fai %n minutu","fai %n minutos"), +"_%n hour ago_::_%n hours ago_" => array("fai %n hora","fai %n hores"), +"today" => "güei", +"yesterday" => "ayeri", +"_%n day ago_::_%n days ago_" => array("fai %n día","fai %n díes"), +"last month" => "mes caberu", +"_%n month ago_::_%n months ago_" => array("fai %n mes","fai %n meses"), +"months ago" => "fai meses", +"last year" => "añu caberu", +"years ago" => "fai años", +"Choose" => "Esbillar", +"Yes" => "Sí", +"No" => "Non", +"_{count} file conflict_::_{count} file conflicts_" => array("",""), +"Which files do you want to keep?" => "¿Qué ficheros quies caltener?", +"Cancel" => "Encaboxar", +"Continue" => "Continuar", +"Shared" => "Compartíu", +"Share" => "Compartir", +"Error" => "Fallu", +"Share link" => "Compartir enllaz", +"Password" => "Contraseña", +"Send" => "Unviar", +"group" => "grupu", +"Unshare" => "Dexar de compartir", +"notify by email" => "notificar per corréu", +"can edit" => "pue editar", +"access control" => "control d'accesu", +"create" => "crear", +"update" => "xubir", +"delete" => "desaniciar", +"share" => "compartir", +"Password protected" => "Contraseña protexida", +"Email sent" => "Corréu unviáu", +"Delete" => "Desaniciar", +"Add" => "Amestar", +"Edit tags" => "Editar etiquetes", +"Username" => "Nome d'usuariu", +"Reset" => "Reaniciar", +"For the best results, please consider using a GNU/Linux server instead." => "Pa los meyores resultaos, por favor considera l'usu d'un sirvidor GNU/Linux nel so llugar.", +"Personal" => "Personal", +"Users" => "Usuarios", +"Cheers!" => "¡Salú!", +"will be used" => "usaráse", +"Finishing …" => "Finando ...", +"Log out" => "Zarrar sesión", +"Lost your password?" => "¿Escaeciesti la to contraseña?", +"Log in" => "Aniciar sesión", +"Alternative Logins" => "Anicios de sesión alternativos", +"Thank you for your patience." => "Gracies pola to paciencia." +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/core/l10n/ca.php b/core/l10n/ca.php index 0a658d515d95ca35759402dbcbdc43bb9af09fbc..214b2eac0e9ca55a7a0b84fd58f382b088be343d 100644 --- a/core/l10n/ca.php +++ b/core/l10n/ca.php @@ -50,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Error en carregar la plantilla de missatge: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} conflicte de fitxer","{count} conflictes de fitxer"), "One file conflict" => "Un fitxer en conflicte", +"New Files" => "Fitxers nous", "Which files do you want to keep?" => "Quin fitxer voleu conservar?", "If you select both versions, the copied file will have a number added to its name." => "Si seleccioneu les dues versions, el fitxer copiat tindrà un número afegit al seu nom.", "Cancel" => "Cancel·la", diff --git a/core/l10n/cs_CZ.php b/core/l10n/cs_CZ.php index ffe34f7828082ff37f7ac742475d491d71685a99..c21d904b233ce6b30a1d0739a065e1e533150a36 100644 --- a/core/l10n/cs_CZ.php +++ b/core/l10n/cs_CZ.php @@ -50,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Chyba při nahrávání šablony zprávy: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} souborový konflikt","{count} souborové konflikty","{count} souborových konfliktů"), "One file conflict" => "Jeden konflikt souboru", +"New Files" => "Nové soubory", "Which files do you want to keep?" => "Které soubory chcete ponechat?", "If you select both versions, the copied file will have a number added to its name." => "Pokud zvolíte obě verze, zkopírovaný soubor bude mít název doplněný o číslo.", "Cancel" => "Zrušit", diff --git a/core/l10n/da.php b/core/l10n/da.php index d3384dac4322d625f0d1b8155cfabdb81e5b7299..c7bda6fd3656d276cf60842d3f87ff183d6a88f8 100644 --- a/core/l10n/da.php +++ b/core/l10n/da.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Fejl ved indlæsning af besked skabelon: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} filkonflikt","{count} filkonflikter"), "One file conflict" => "En filkonflikt", +"New Files" => "Nye filer", "Which files do you want to keep?" => "Hvilke filer ønsker du at beholde?", "If you select both versions, the copied file will have a number added to its name." => "Hvis du vælger begge versioner, vil den kopierede fil få tilføjet et nummer til sit navn.", "Cancel" => "Annuller", diff --git a/core/l10n/de.php b/core/l10n/de.php index 79edfb725d77271d33892e84b694a7a3aa1dcb49..fabf35440cb3966da326a496ce3bfd6cd34c905f 100644 --- a/core/l10n/de.php +++ b/core/l10n/de.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Fehler beim Laden der Nachrichtenvorlage: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} Dateikonflikt","{count} Dateikonflikte"), "One file conflict" => "Ein Dateikonflikt", +"New Files" => "Neue Dateien", +"Already existing files" => "Die Dateien existieren bereits", "Which files do you want to keep?" => "Welche Dateien möchtest Du behalten?", "If you select both versions, the copied file will have a number added to its name." => "Wenn Du beide Versionen auswählst, erhält die kopierte Datei eine Zahl am Ende des Dateinamens.", "Cancel" => "Abbrechen", diff --git a/core/l10n/de_CH.php b/core/l10n/de_CH.php index 42b8eb3bceae67eec06f5c7db204341017ba1369..eb2cfd233d3b454496cb4cf98711765250a0742d 100644 --- a/core/l10n/de_CH.php +++ b/core/l10n/de_CH.php @@ -40,6 +40,7 @@ $TRANSLATIONS = array( "No" => "Nein", "Ok" => "OK", "_{count} file conflict_::_{count} file conflicts_" => array("",""), +"New Files" => "Neue Dateien", "Cancel" => "Abbrechen", "Shared" => "Geteilt", "Share" => "Teilen", diff --git a/core/l10n/de_DE.php b/core/l10n/de_DE.php index a0877e792e265f1517ce58bb507a476208a045d7..a65714f26f62d40ca59377911ef73243376ab6d4 100644 --- a/core/l10n/de_DE.php +++ b/core/l10n/de_DE.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Fehler beim Laden der Nachrichtenvorlage: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} Dateikonflikt","{count} Dateikonflikte"), "One file conflict" => "Ein Dateikonflikt", +"New Files" => "Neue Dateien", +"Already existing files" => "Die Dateien existieren bereits", "Which files do you want to keep?" => "Welche Dateien möchten Sie behalten?", "If you select both versions, the copied file will have a number added to its name." => "Wenn Sie beide Versionen auswählen, erhält die kopierte Datei eine Zahl am Ende des Dateinamens.", "Cancel" => "Abbrechen", diff --git a/core/l10n/el.php b/core/l10n/el.php index ed7792b7261ae320620034f61067be9b3588c058..c899427ae3090d1950241f9f977d3f1c1e8d1884 100644 --- a/core/l10n/el.php +++ b/core/l10n/el.php @@ -1,5 +1,6 @@ "Η ημερομηνία λήξης είναι στο παρελθόν.", "Couldn't send mail to following users: %s " => "Αδυναμία αποστολής μηνύματος στους ακόλουθους χρήστες: %s", "Turned on maintenance mode" => "Η κατάσταση συντήρησης ενεργοποιήθηκε", "Turned off maintenance mode" => "Η κατάσταση συντήρησης απενεργοποιήθηκε", @@ -49,14 +50,17 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Σφάλμα φόρτωσης προτύπου μηνυμάτων: {σφάλμα}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} αρχείο διαφέρει","{count} αρχεία διαφέρουν"), "One file conflict" => "Ένα αρχείο διαφέρει", +"New Files" => "Νέα Αρχεία", "Which files do you want to keep?" => "Ποια αρχεία θέλετε να κρατήσετε;", "If you select both versions, the copied file will have a number added to its name." => "Εάν επιλέξετε και τις δυο εκδοχές, ένας αριθμός θα προστεθεί στο αντιγραφόμενο αρχείο.", "Cancel" => "Άκυρο", "Continue" => "Συνέχεια", "(all selected)" => "(όλα τα επιλεγμένα)", "({count} selected)" => "({count} επιλέχθησαν)", +"Error loading file exists template" => "Σφάλμα κατά την φόρτωση του προτύπου ύπαρξης αρχείου", "Very weak password" => "Πολύ αδύναμο συνθηματικό", "Weak password" => "Αδύναμο συνθηματικό", +"So-so password" => "Μέτριο συνθηματικό", "Good password" => "Καλό συνθηματικό", "Strong password" => "Δυνατό συνθηματικό", "Shared" => "Κοινόχρηστα", @@ -119,6 +123,8 @@ $TRANSLATIONS = array( "To login page" => "Σελίδα εισόδου", "New password" => "Νέο συνθηματικό", "Reset password" => "Επαναφορά συνθηματικού", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Το Mac OS X δεν υποστηρίζεται και το %s δεν θα λειτουργήσει σωστά σε αυτή την πλατφόρμα. Χρησιμοποιείτε με δική σας ευθύνη!", +"For the best results, please consider using a GNU/Linux server instead." => "Για καλύτερα αποτελέσματα, παρακαλούμε εξετάστε την μετατροπή σε έναν διακομιστή GNU/Linux.", "Personal" => "Προσωπικά", "Users" => "Χρήστες", "Apps" => "Εφαρμογές", @@ -144,6 +150,7 @@ $TRANSLATIONS = array( "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Ο κατάλογος δεδομένων και τα αρχεία σας είναι πιθανό προσβάσιμα από το internet γιατί δεν δουλεύει το αρχείο .htaccess.", "For information how to properly configure your server, please see the documentation." => "Για πληροφορίες πως να ρυθμίσετε ορθά τον διακομιστή σας, παρακαλώ δείτε την τεκμηρίωση.", "Create an admin account" => "Δημιουργήστε έναν λογαριασμό διαχειριστή", +"Storage & database" => "Αποθήκευση & βάση δεδομένων", "Data folder" => "Φάκελος δεδομένων", "Configure the database" => "Ρύθμιση της βάσης δεδομένων", "will be used" => "θα χρησιμοποιηθούν", @@ -166,6 +173,7 @@ $TRANSLATIONS = array( "remember" => "απομνημόνευση", "Log in" => "Είσοδος", "Alternative Logins" => "Εναλλακτικές Συνδέσεις", +"Hey there,

    just letting you know that %s shared %s with you.
    View it!

    " => "Γειά χαρά,

    απλά σας ενημερώνω πως ο %s μοιράστηκε το%s με εσάς.
    Δείτε το!

    ", "This ownCloud instance is currently in single user mode." => "Αυτή η εγκατάσταση ownCloud είναι τώρα σε κατάσταση ενός χρήστη.", "This means only administrators can use the instance." => "Αυτό σημαίνει ότι μόνο διαχειριστές μπορούν να χρησιμοποιήσουν την εγκατάσταση.", "Contact your system administrator if this message persists or appeared unexpectedly." => "Επικοινωνήστε με το διαχειριστή του συστήματος αν αυτό το μήνυμα συνεχίζει να εμφανίζεται ή εμφανίστηκε απρόσμενα.", diff --git a/core/l10n/en_GB.php b/core/l10n/en_GB.php index bc36f5a4446b4483918f6d87c19cd2c790c8585c..215bae92d1c6cdf8a98364b7271f41634e71b19e 100644 --- a/core/l10n/en_GB.php +++ b/core/l10n/en_GB.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Error loading message template: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} file conflict","{count} file conflicts"), "One file conflict" => "One file conflict", +"New Files" => "New Files", +"Already existing files" => "Already existing files", "Which files do you want to keep?" => "Which files do you wish to keep?", "If you select both versions, the copied file will have a number added to its name." => "If you select both versions, the copied file will have a number added to its name.", "Cancel" => "Cancel", diff --git a/core/l10n/eo.php b/core/l10n/eo.php index f264b7ed7a7fb56e30425661b002fcf2e5241f60..05d28efb66be01c30ab716e777210dbf816aa73d 100644 --- a/core/l10n/eo.php +++ b/core/l10n/eo.php @@ -41,6 +41,7 @@ $TRANSLATIONS = array( "Ok" => "Akcepti", "_{count} file conflict_::_{count} file conflicts_" => array("{count} dosierkonflikto","{count} dosierkonfliktoj"), "One file conflict" => "Unu dosierkonflikto", +"New Files" => "Novaj dosieroj", "Which files do you want to keep?" => "Kiujn dosierojn vi volas konservi?", "If you select both versions, the copied file will have a number added to its name." => "Se vi elektos ambaŭ eldonojn, la kopiota dosiero havos numeron aldonitan al sia nomo.", "Cancel" => "Nuligi", diff --git a/core/l10n/es.php b/core/l10n/es.php index 7f4d46aa1f1a75feaa8401dc73198f57653b043e..cb2d09d60fe13f528d035aa74ce06cc6ac0e4bf7 100644 --- a/core/l10n/es.php +++ b/core/l10n/es.php @@ -1,6 +1,6 @@ "La fecha de caducidad está en el pasado.", +"Expiration date is in the past." => "Ha pasado la fecha de caducidad", "Couldn't send mail to following users: %s " => "No se pudo enviar el mensaje a los siguientes usuarios: %s", "Turned on maintenance mode" => "Modo mantenimiento activado", "Turned off maintenance mode" => "Modo mantenimiento desactivado", @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Error cargando plantilla del mensaje: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} conflicto de archivo","{count} conflictos de archivo"), "One file conflict" => "On conflicto de archivo", +"New Files" => "Nuevos Archivos", +"Already existing files" => "Archivos ya existentes", "Which files do you want to keep?" => "¿Que archivos deseas mantener?", "If you select both versions, the copied file will have a number added to its name." => "Si seleccionas ambas versiones, el archivo copiado tendrá añadido un número en su nombre.", "Cancel" => "Cancelar", @@ -105,7 +107,7 @@ $TRANSLATIONS = array( "Edit tags" => "Editar etiquetas", "Error loading dialog template: {error}" => "Error cargando plantilla de diálogo: {error}", "No tags selected for deletion." => "No hay etiquetas seleccionadas para borrar.", -"Please reload the page." => "Vuelva a cargar la página.", +"Please reload the page." => "Recargue/Actualice la página", "The update was unsuccessful. Please report this issue to the ownCloud community." => "La actualización ha fracasado. Por favor, informe de este problema a la Comunidad de ownCloud.", "The update was successful. Redirecting you to ownCloud now." => "La actualización se ha realizado con éxito. Redireccionando a ownCloud ahora.", "%s password reset" => "%s restablecer contraseña", @@ -179,6 +181,6 @@ $TRANSLATIONS = array( "Thank you for your patience." => "Gracias por su paciencia.", "Updating ownCloud to version %s, this may take a while." => "Actualizando ownCloud a la versión %s, esto puede demorar un tiempo.", "This ownCloud instance is currently being updated, which may take a while." => "Esta versión de owncloud se está actualizando, esto puede demorar un tiempo.", -"Please reload this page after a short time to continue using ownCloud." => "Por favor , recargue esta instancia de onwcloud tras un corto periodo de tiempo y continue usándolo." +"Please reload this page after a short time to continue using ownCloud." => "Por favor, recargue la página tras un corto periodo de tiempo para continuar usando ownCloud" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/core/l10n/es_AR.php b/core/l10n/es_AR.php index b5b37d4825b2ae4223b575527913211b637233c2..c9d270edefab0425cc3e616fbc6f2648c1fa29e8 100644 --- a/core/l10n/es_AR.php +++ b/core/l10n/es_AR.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Error cargando la plantilla del mensaje: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("un archivo en conflicto","{count} archivos en conflicto"), "One file conflict" => "Un archivo en conflicto", +"New Files" => "Nuevos archivos", "Which files do you want to keep?" => "¿Qué archivos deseas retener?", "If you select both versions, the copied file will have a number added to its name." => "Si tu seleccionas ambas versiones, el archivo copiado tendrá un número agregado a su nombre.", "Cancel" => "Cancelar", diff --git a/core/l10n/et_EE.php b/core/l10n/et_EE.php index 5a2e34ff3a0e1cc9c270c0a3f14ac791b01049f1..422caac9c15b01be0569919b4d62840d59e9a9e0 100644 --- a/core/l10n/et_EE.php +++ b/core/l10n/et_EE.php @@ -1,5 +1,6 @@ "Aegumise kuupäev on minevikus.", "Couldn't send mail to following users: %s " => "Kirja saatmine järgnevatele kasutajatele ebaõnnestus: %s ", "Turned on maintenance mode" => "Haldusrežiimis sisse lülitatud", "Turned off maintenance mode" => "Haldusrežiimis välja lülitatud", @@ -49,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Viga sõnumi malli laadimisel: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} failikonflikt","{count} failikonflikti"), "One file conflict" => "Üks failikonflikt", +"New Files" => "Uued failid", "Which files do you want to keep?" => "Milliseid faile sa soovid alles hoida?", "If you select both versions, the copied file will have a number added to its name." => "Kui valid mõlemad versioonid, siis lisatakse kopeeritud faili nimele number.", "Cancel" => "Loobu", @@ -56,6 +58,11 @@ $TRANSLATIONS = array( "(all selected)" => "(kõik valitud)", "({count} selected)" => "({count} valitud)", "Error loading file exists template" => "Viga faili olemasolu malli laadimisel", +"Very weak password" => "Väga nõrk parool", +"Weak password" => "Nõrk parool", +"So-so password" => "Enam-vähem sobiv parool", +"Good password" => "Hea parool", +"Strong password" => "Väga hea parool", "Shared" => "Jagatud", "Share" => "Jaga", "Error" => "Viga", @@ -103,6 +110,7 @@ $TRANSLATIONS = array( "The update was unsuccessful. Please report this issue to the ownCloud community." => "Uuendus ebaõnnestus. Palun teavita probleemidest ownCloud kogukonda.", "The update was successful. Redirecting you to ownCloud now." => "Uuendus oli edukas. Kohe suunatakse Sind ownCloudi.", "%s password reset" => "%s parooli lähtestus", +"A problem has occurred whilst sending the email, please contact your administrator." => "Tekkis tõrge e-posti saatmisel, palun kontakteeru administraatoriga.", "Use the following link to reset your password: {link}" => "Kasuta järgnevat linki oma parooli taastamiseks: {link}", "The link to reset your password has been sent to your email.
    If you do not receive it within a reasonable amount of time, check your spam/junk folders.
    If it is not there ask your local administrator ." => "Link parooli vahetuseks on saadetud Sinu e-posti aadressile.
    Kui kiri pole saabunud mõistliku aja jooksul, siis kontrolli oma spam-/rämpskirjade katalooge.
    Kui kirja pole ka seal, siis küsi abi süsteemihaldurilt.", "Request failed!
    Did you make sure your email/username was right?" => "Päring ebaõnnestus!
    Oled sa veendunud, et e-post/kasutajanimi on õiged?", @@ -115,6 +123,8 @@ $TRANSLATIONS = array( "To login page" => "Sisselogimise lehele", "New password" => "Uus parool", "Reset password" => "Nulli parool", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X ei ole toetatud ja %s ei pruugi korralikult toimida sellel platvormil. Kasuta seda omal vastutusel!", +"For the best results, please consider using a GNU/Linux server instead." => "Parema tulemuse saavitamiseks palun kaalu serveris GNU/Linux kasutamist.", "Personal" => "Isiklik", "Users" => "Kasutajad", "Apps" => "Rakendused", @@ -140,6 +150,7 @@ $TRANSLATIONS = array( "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Su andmete kataloog ja failid on tõenäoliselt internetist vabalt saadaval kuna .htaccess fail ei toimi.", "For information how to properly configure your server, please see the documentation." => "Serveri korrektseks seadistuseks palun tutvu dokumentatsiooniga.", "Create an admin account" => "Loo admini konto", +"Storage & database" => "Andmehoidla ja andmebaas", "Data folder" => "Andmete kaust", "Configure the database" => "Seadista andmebaasi", "will be used" => "kasutatakse", @@ -162,6 +173,7 @@ $TRANSLATIONS = array( "remember" => "pea meeles", "Log in" => "Logi sisse", "Alternative Logins" => "Alternatiivsed sisselogimisviisid", +"Hey there,

    just letting you know that %s shared %s with you.
    View it!

    " => "Hei,

    annan teada, et %s jagas sinuga %s. Vaata seda!

    ", "This ownCloud instance is currently in single user mode." => "See ownCloud on momendil seadistatud ühe kasutaja jaoks.", "This means only administrators can use the instance." => "See tähendab, et seda saavad kasutada ainult administraatorid.", "Contact your system administrator if this message persists or appeared unexpectedly." => "Kontakteeru oma süsteemihalduriga, kui see teade püsib või on tekkinud ootamatult.", diff --git a/core/l10n/eu.php b/core/l10n/eu.php index 33c98fb9b90e76238f80de8494dac7d5b6ee6051..8fd554485dbe004d79b49f59f1a7e6fcd4c1271c 100644 --- a/core/l10n/eu.php +++ b/core/l10n/eu.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Errorea mezu txantiloia kargatzean: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("fitxategi {count}ek konfliktua sortu du","{count} fitxategik konfliktua sortu dute"), "One file conflict" => "Fitxategi batek konfliktua sortu du", +"New Files" => "Fitxategi Berriak", "Which files do you want to keep?" => "Ze fitxategi mantendu nahi duzu?", "If you select both versions, the copied file will have a number added to its name." => "Bi bertsioak hautatzen badituzu, kopiatutako fitxategiaren izenean zenbaki bat atxikituko zaio.", "Cancel" => "Ezeztatu", diff --git a/core/l10n/fa.php b/core/l10n/fa.php index 3e7e246e82719397b3b00e2779b06997e36d78b6..a349d3b77044a66cd4d29f25a33f222691089453 100644 --- a/core/l10n/fa.php +++ b/core/l10n/fa.php @@ -37,6 +37,7 @@ $TRANSLATIONS = array( "No" => "نه", "Ok" => "قبول", "_{count} file conflict_::_{count} file conflicts_" => array(""), +"New Files" => "فایل های جدید", "Cancel" => "منصرف شدن", "Shared" => "اشتراک گذاشته شده", "Share" => "اشتراک‌گذاری", diff --git a/core/l10n/fi_FI.php b/core/l10n/fi_FI.php index 0af7503ee9d8e1ad3dc4365ca0c974cb1d491060..7797d17c872e98593a6f73ca83612e25ce5508bc 100644 --- a/core/l10n/fi_FI.php +++ b/core/l10n/fi_FI.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Virhe ladatessa viestipohjaa: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} tiedoston ristiriita","{count} tiedoston ristiriita"), "One file conflict" => "Yhden tiedoston ristiriita", +"New Files" => "Uudet tiedostot", +"Already existing files" => "Jo olemassa olevat tiedostot", "Which files do you want to keep?" => "Mitkä tiedostot haluat säilyttää?", "If you select both versions, the copied file will have a number added to its name." => "Jos valitset kummatkin versiot, kopioidun tiedoston nimeen lisätään numero.", "Cancel" => "Peru", @@ -122,6 +124,8 @@ $TRANSLATIONS = array( "To login page" => "Kirjautumissivulle", "New password" => "Uusi salasana", "Reset password" => "Palauta salasana", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X ei ole tuettu, joten %s ei toimi kunnolla tällä alustalla. Käytä omalla vastuulla!", +"For the best results, please consider using a GNU/Linux server instead." => "Käytä parhaan lopputuloksen saamiseksi GNU/Linux-palvelinta.", "Personal" => "Henkilökohtainen", "Users" => "Käyttäjät", "Apps" => "Sovellukset", diff --git a/core/l10n/fr.php b/core/l10n/fr.php index 3754e8c9e07e01ae8a2a82e3f3ffecd5d5cf75ce..623f129c860dabb978155d494f22351784b7f4f0 100644 --- a/core/l10n/fr.php +++ b/core/l10n/fr.php @@ -1,5 +1,6 @@ "La date d'expiration est dans le passé.", "Couldn't send mail to following users: %s " => "Impossible d'envoyer un mail aux utilisateurs suivant : %s", "Turned on maintenance mode" => "Basculé en mode maintenance", "Turned off maintenance mode" => "Basculé en mode production (non maintenance)", @@ -49,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Erreur de chargement du modèle de message : {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} fichier en conflit","{count} fichiers en conflit"), "One file conflict" => "Un conflit de fichier", +"New Files" => "Nouveaux fichiers", +"Already existing files" => "Fichiers déjà existants", "Which files do you want to keep?" => "Quels fichiers désirez-vous garder ?", "If you select both versions, the copied file will have a number added to its name." => "Si vous sélectionnez les deux versions, un nombre sera ajouté au nom du fichier copié.", "Cancel" => "Annuler", @@ -121,6 +124,8 @@ $TRANSLATIONS = array( "To login page" => "Retour à la page d'authentification", "New password" => "Nouveau mot de passe", "Reset password" => "Réinitialiser le mot de passe", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X n'est pas supporté et %s ne fonctionnera pas correctement sur cette plateforme. Son utilisation est à vos risques et périls !", +"For the best results, please consider using a GNU/Linux server instead." => "Pour des résultats meilleurs encore, pensez à utiliser un serveur GNU/Linux à la place.", "Personal" => "Personnel", "Users" => "Utilisateurs", "Apps" => "Applications", diff --git a/core/l10n/gl.php b/core/l10n/gl.php index c1c678e7e3fe074521df974ef6d8740e931ce58b..eb9f1af5657fa5f7862a36a97df8aa22157a5521 100644 --- a/core/l10n/gl.php +++ b/core/l10n/gl.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Produciuse un erro ao cargar o modelo da mensaxe: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} conflito de ficheiro","{count} conflitos de ficheiros"), "One file conflict" => "Un conflito de ficheiro", +"New Files" => "Ficheiros novos", +"Already existing files" => "Ficheiros xa existentes", "Which files do you want to keep?" => "Que ficheiros quere conservar?", "If you select both versions, the copied file will have a number added to its name." => "Se selecciona ambas versións, o ficheiro copiado terá un número engadido ao nome.", "Cancel" => "Cancelar", diff --git a/core/l10n/he.php b/core/l10n/he.php index 4579626f12d1990b8a8ef4ddfeb3c40d218a9241..8fb7373a143be71ded926d31a368f98b06394842 100644 --- a/core/l10n/he.php +++ b/core/l10n/he.php @@ -37,6 +37,7 @@ $TRANSLATIONS = array( "No" => "לא", "Ok" => "בסדר", "_{count} file conflict_::_{count} file conflicts_" => array("",""), +"New Files" => "קבצים חדשים", "Cancel" => "ביטול", "Shared" => "שותף", "Share" => "שתף", diff --git a/core/l10n/hu_HU.php b/core/l10n/hu_HU.php index e81991ec7adc93e10cf302fb5f2d9bb03a72f7f5..096b28e2d9be4961ac1deed041c7715af2f9ac4a 100644 --- a/core/l10n/hu_HU.php +++ b/core/l10n/hu_HU.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Nem sikerült betölteni az üzenet sablont: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} fájl ütközik","{count} fájl ütközik"), "One file conflict" => "Egy file ütközik", +"New Files" => "Új fájlok", "Which files do you want to keep?" => "Melyik file-okat akarod megtartani?", "If you select both versions, the copied file will have a number added to its name." => "Ha kiválasztod mindazokaz a verziókat, a másolt fileok neve sorszámozva lesz.", "Cancel" => "Mégsem", diff --git a/core/l10n/it.php b/core/l10n/it.php index 2f0017263fa05ebb1c3d6eb9850e9f5db024ed32..98d0d5e3b0e78e4ebd58f6df2eba9016120fafbd 100644 --- a/core/l10n/it.php +++ b/core/l10n/it.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Errore durante il caricamento del modello di messaggio: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} file in conflitto","{count} file in conflitto"), "One file conflict" => "Un file in conflitto", +"New Files" => "File nuovi", +"Already existing files" => "File già esistenti", "Which files do you want to keep?" => "Quali file vuoi mantenere?", "If you select both versions, the copied file will have a number added to its name." => "Se selezioni entrambe le versioni, sarà aggiunto un numero al nome del file copiato.", "Cancel" => "Annulla", diff --git a/core/l10n/ja.php b/core/l10n/ja.php index eb3e6882578256303d39756511bc7d6abeb5b00e..3a99f0e598b5a7219d41ffe009a42ccfe9f458dd 100644 --- a/core/l10n/ja.php +++ b/core/l10n/ja.php @@ -1,5 +1,6 @@ "有効期限が切れています。", "Couldn't send mail to following users: %s " => "次のユーザーにメールを送信できませんでした: %s", "Turned on maintenance mode" => "メンテナンスモードがオンになりました", "Turned off maintenance mode" => "メンテナンスモードがオフになりました", @@ -49,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "メッセージテンプレートの読み込みエラー: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} ファイルが競合"), "One file conflict" => "1ファイルが競合", +"New Files" => "新しいファイル", "Which files do you want to keep?" => "どちらのファイルを保持したいですか?", "If you select both versions, the copied file will have a number added to its name." => "両方のバージョンを選択した場合は、ファイル名の後ろに数字を追加したファイルのコピーを作成します。", "Cancel" => "キャンセル", @@ -121,6 +123,8 @@ $TRANSLATIONS = array( "To login page" => "ログインページへ戻る", "New password" => "新しいパスワードを入力", "Reset password" => "パスワードをリセット", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。", +"For the best results, please consider using a GNU/Linux server instead." => "最も良い方法としては、代わりにGNU/Linuxサーバーを利用することをご検討ください。", "Personal" => "個人", "Users" => "ユーザー", "Apps" => "アプリ", diff --git a/core/l10n/jv.php b/core/l10n/jv.php new file mode 100644 index 0000000000000000000000000000000000000000..ffcdde48d47cbbe4730b36aec880f7e1642688fb --- /dev/null +++ b/core/l10n/jv.php @@ -0,0 +1,9 @@ + array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day ago_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("",""), +"_{count} file conflict_::_{count} file conflicts_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/core/l10n/ka_GE.php b/core/l10n/ka_GE.php index 0070fd7994e6e999b46088f18135926af7f4f17c..a76a8866541d6268f1e18d3aa28d4b5f0e57986d 100644 --- a/core/l10n/ka_GE.php +++ b/core/l10n/ka_GE.php @@ -37,6 +37,7 @@ $TRANSLATIONS = array( "No" => "არა", "Ok" => "დიახ", "_{count} file conflict_::_{count} file conflicts_" => array(""), +"New Files" => "ახალი ფაილები", "Cancel" => "უარყოფა", "Shared" => "გაზიარებული", "Share" => "გაზიარება", diff --git a/core/l10n/lv.php b/core/l10n/lv.php index 505bf46b4c9c5ffdb7be39d7fef1818e5527a2a1..683ff2c129a53e2549437d9346d9157a1d31b439 100644 --- a/core/l10n/lv.php +++ b/core/l10n/lv.php @@ -37,6 +37,7 @@ $TRANSLATIONS = array( "No" => "Nē", "Ok" => "Labi", "_{count} file conflict_::_{count} file conflicts_" => array("","",""), +"New Files" => "Jaunās datnes", "Cancel" => "Atcelt", "Shared" => "Kopīgs", "Share" => "Dalīties", diff --git a/core/l10n/nb_NO.php b/core/l10n/nb_NO.php index 43141bc431f85ed322e5cdbb236baa581e7641ff..c47599f5a1702fcea3318bfeff7d32836eb7236c 100644 --- a/core/l10n/nb_NO.php +++ b/core/l10n/nb_NO.php @@ -56,6 +56,10 @@ $TRANSLATIONS = array( "(all selected)" => "(alle valgt)", "({count} selected)" => "({count} valgt)", "Error loading file exists template" => "Feil ved lasting av \"filen eksisterer\"-mal", +"Very weak password" => "Veldig svakt passord", +"Weak password" => "Svakt passord", +"Good password" => "Bra passord", +"Strong password" => "Sterkt passord", "Shared" => "Delt", "Share" => "Del", "Error" => "Feil", @@ -140,6 +144,7 @@ $TRANSLATIONS = array( "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Datamappen og filene dine er sannsynligvis tilgjengelig fra Internett fordi .htaccess-filen ikke fungerer.", "For information how to properly configure your server, please see the documentation." => "For informasjon om hvordan du setter opp serveren din riktig, se dokumentasjonen.", "Create an admin account" => "opprett en administrator-konto", +"Storage & database" => "Lagring og database", "Data folder" => "Datamappe", "Configure the database" => "Konfigurer databasen", "will be used" => "vil bli brukt", diff --git a/core/l10n/nl.php b/core/l10n/nl.php index 05cef6afd5a06a6384f93bc35a755f99ce31037f..b09509e6290822e4fec83c0b2c4421e1e21cdbd1 100644 --- a/core/l10n/nl.php +++ b/core/l10n/nl.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Fout bij laden berichtensjabloon: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} bestandsconflict","{count} bestandsconflicten"), "One file conflict" => "Een bestandsconflict", +"New Files" => "Nieuwe bestanden", +"Already existing files" => "Al aanwezige bestanden", "Which files do you want to keep?" => "Welke bestanden wilt u bewaren?", "If you select both versions, the copied file will have a number added to its name." => "Als u beide versies selecteerde, zal het gekopieerde bestand een nummer aan de naam toegevoegd krijgen.", "Cancel" => "Annuleer", diff --git a/core/l10n/pl.php b/core/l10n/pl.php index 17fde36c7cd20fb4e0038ad11c410a2a62756429..fe0cf1458323daae504dee607d6a3dd3760be04c 100644 --- a/core/l10n/pl.php +++ b/core/l10n/pl.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Błąd podczas ładowania szablonu wiadomości: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} konfliktów plików","{count} konfliktów plików","{count} konfliktów plików"), "One file conflict" => "Konflikt pliku", +"New Files" => "Nowe pliki", +"Already existing files" => "Już istniejące pliki", "Which files do you want to keep?" => "Które pliki chcesz zachować?", "If you select both versions, the copied file will have a number added to its name." => "Jeśli wybierzesz obie wersje, skopiowany plik będzie miał dodany numerek w nazwie", "Cancel" => "Anuluj", diff --git a/core/l10n/pl_PL.php b/core/l10n/pl_PL.php deleted file mode 100644 index 15c376eb9544ebe6b78ce2e75e48fa8930dcb1e6..0000000000000000000000000000000000000000 --- a/core/l10n/pl_PL.php +++ /dev/null @@ -1,6 +0,0 @@ - "Ustawienia", -"Username" => "Nazwa użytkownika" -); -$PLURAL_FORMS = "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/core/l10n/pt_BR.php b/core/l10n/pt_BR.php index b31925cdf79bc21c51ed2a95c5fc6204e3925655..3545426b670d3d9bc136e5505a64c88774cd6efc 100644 --- a/core/l10n/pt_BR.php +++ b/core/l10n/pt_BR.php @@ -50,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Erro no carregamento de modelo de mensagem: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} conflito de arquivo","{count} conflitos de arquivos"), "One file conflict" => "Conflito em um arquivo", +"New Files" => "Novos Arquivos", +"Already existing files" => "Arquivos já existentes", "Which files do you want to keep?" => "Qual arquivo você quer manter?", "If you select both versions, the copied file will have a number added to its name." => "Se você selecionar ambas as versões, o arquivo copiado terá um número adicionado ao seu nome.", "Cancel" => "Cancelar", diff --git a/core/l10n/pt_PT.php b/core/l10n/pt_PT.php index a4d6785cd5ea2b6f78b4832f9757ff685c85dcb9..bb1b6011a6ba5a7f3cb3c025575e8c0c9656e0da 100644 --- a/core/l10n/pt_PT.php +++ b/core/l10n/pt_PT.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Erro ao carregar o template: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} conflicto de ficheiro","{count} conflitos de ficheiro"), "One file conflict" => "Um conflito no ficheiro", +"New Files" => "Ficheiros Novos", "Which files do you want to keep?" => "Quais os ficheiros que pretende manter?", "If you select both versions, the copied file will have a number added to its name." => "Se escolher ambas as versões, o ficheiro copiado irá ter um número adicionado ao seu nome.", "Cancel" => "Cancelar", diff --git a/core/l10n/ru.php b/core/l10n/ru.php index 8d84e7d31bc33888af8ae26b1ce18321517e03c0..aa784088f7a2b4925ce2da70114f3d2b2421c710 100644 --- a/core/l10n/ru.php +++ b/core/l10n/ru.php @@ -1,5 +1,6 @@ "Дата истечения срока действия в прошлом.", "Couldn't send mail to following users: %s " => "Невозможно отправить письмо следующим пользователям: %s", "Turned on maintenance mode" => "Режим отладки включён", "Turned off maintenance mode" => "Режим отладки отключён", @@ -49,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Ошибка загрузки шаблона сообщений: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} конфликт в файлах","{count} конфликта в файлах","{count} конфликтов в файлах"), "One file conflict" => "Один конфликт в файлах", +"New Files" => "Новые файлы", "Which files do you want to keep?" => "Какие файлы вы хотите сохранить?", "If you select both versions, the copied file will have a number added to its name." => "При выборе обоих версий, к названию копируемого файла будет добавлена цифра", "Cancel" => "Отменить", @@ -56,6 +58,11 @@ $TRANSLATIONS = array( "(all selected)" => "(выбраны все)", "({count} selected)" => "({count} выбрано)", "Error loading file exists template" => "Ошибка при загрузке шаблона существующего файла", +"Very weak password" => "Очень слабый пароль", +"Weak password" => "Слабый пароль", +"So-so password" => "Так себе пароль", +"Good password" => "Хороший пароль", +"Strong password" => "Устойчивый к взлому пароль", "Shared" => "Общие", "Share" => "Открыть доступ", "Error" => "Ошибка", @@ -103,6 +110,7 @@ $TRANSLATIONS = array( "The update was unsuccessful. Please report this issue to the ownCloud community." => "При обновлении произошла ошибка. Пожалуйста сообщите об этом в ownCloud сообщество.", "The update was successful. Redirecting you to ownCloud now." => "Обновление прошло успешно. Перенаправляемся в Ваш ownCloud...", "%s password reset" => "%s сброс пароля", +"A problem has occurred whilst sending the email, please contact your administrator." => "Произошла ошибка при отправке сообщения электронной почты, пожалуйста, свяжитесь с Вашим администратором.", "Use the following link to reset your password: {link}" => "Используйте следующую ссылку чтобы сбросить пароль: {link}", "The link to reset your password has been sent to your email.
    If you do not receive it within a reasonable amount of time, check your spam/junk folders.
    If it is not there ask your local administrator ." => "Ссылка для сброса пароля отправлена вам ​​по электронной почте.
    Если вы не получите письмо в пределах одной-двух минут, проверьте папку Спам.
    Если письма там нет, обратитесь к своему администратору.", "Request failed!
    Did you make sure your email/username was right?" => "Запрос не удался. Вы уверены, что email или имя пользователя указаны верно?", @@ -115,6 +123,8 @@ $TRANSLATIONS = array( "To login page" => "На страницу авторизации", "New password" => "Новый пароль", "Reset password" => "Сбросить пароль", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X не поддерживается и %s не будет работать правильно на этой платформе. Используйте ее на свой страх и риск!", +"For the best results, please consider using a GNU/Linux server instead." => "Для достижения наилучших результатов, пожалуйста, рассмотрите возможность использовать взамен GNU/Linux сервер.", "Personal" => "Личное", "Users" => "Пользователи", "Apps" => "Приложения", @@ -140,6 +150,7 @@ $TRANSLATIONS = array( "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Ваша папка с данными и файлы возможно доступны из интернета потому что файл .htaccess не работает.", "For information how to properly configure your server, please see the documentation." => "Для информации, как правильно настроить Ваш сервер, пожалуйста загляните в документацию.", "Create an admin account" => "Создать учётную запись администратора", +"Storage & database" => "Система хранения данных & база данных", "Data folder" => "Директория с данными", "Configure the database" => "Настройка базы данных", "will be used" => "будет использовано", @@ -162,6 +173,7 @@ $TRANSLATIONS = array( "remember" => "запомнить", "Log in" => "Войти", "Alternative Logins" => "Альтернативные имена пользователя", +"Hey there,

    just letting you know that %s shared %s with you.
    View it!

    " => "Здравствуйте,

    просто даём вам знать, что %s открыл доступ к %s для вас.
    Посмотреть!

    ", "This ownCloud instance is currently in single user mode." => "Эта установка ownCloud в настоящее время в однопользовательском режиме.", "This means only administrators can use the instance." => "Это значит, что только администраторы могут использовать эту установку.", "Contact your system administrator if this message persists or appeared unexpectedly." => "Обратитесь к вашему системному администратору если это сообщение не исчезает или появляется неожиданно.", diff --git a/core/l10n/sk_SK.php b/core/l10n/sk_SK.php index bb3c9863ce2c2c5f5c848a3284fe38ee30e699a8..1b717bc412ee6c6e5c3377b96171cbcb2924d464 100644 --- a/core/l10n/sk_SK.php +++ b/core/l10n/sk_SK.php @@ -1,5 +1,6 @@ " \t\nDátum expirácie spadá do minulosti.", "Couldn't send mail to following users: %s " => "Nebolo možné odoslať email týmto používateľom: %s ", "Turned on maintenance mode" => "Mód údržby je zapnutý", "Turned off maintenance mode" => "Mód údržby e vypnutý", @@ -49,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Chyba pri nahrávaní šablóny správy: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} konflikt súboru","{count} konflikty súboru","{count} konfliktov súboru"), "One file conflict" => "Jeden konflikt súboru", +"New Files" => "Nové súbory", "Which files do you want to keep?" => "Ktoré súbory chcete ponechať?", "If you select both versions, the copied file will have a number added to its name." => "Ak zvolíte obe verzie, názov nakopírovaného súboru bude doplnený o číslo.", "Cancel" => "Zrušiť", @@ -56,6 +58,11 @@ $TRANSLATIONS = array( "(all selected)" => "(všetko vybrané)", "({count} selected)" => "({count} vybraných)", "Error loading file exists template" => "Chyba pri nahrávaní šablóny existencie súboru", +"Very weak password" => "Veľmi slabé heslo", +"Weak password" => "Slabé heslo", +"So-so password" => "Priemerné heslo", +"Good password" => "Dobré heslo", +"Strong password" => "Silné heslo", "Shared" => "Zdieľané", "Share" => "Zdieľať", "Error" => "Chyba", @@ -103,6 +110,7 @@ $TRANSLATIONS = array( "The update was unsuccessful. Please report this issue to the ownCloud community." => "Aktualizácia nebola úspešná. Problém nahláste ownCloud comunite.", "The update was successful. Redirecting you to ownCloud now." => "Aktualizácia bola úspešná. Presmerovávam vás na prihlasovaciu stránku.", "%s password reset" => "reset hesla %s", +"A problem has occurred whilst sending the email, please contact your administrator." => "Vyskytol sa problém pri odosielaní emailu, prosím obráťte sa na správcu.", "Use the following link to reset your password: {link}" => "Použite nasledujúci odkaz pre obnovenie vášho hesla: {link}", "The link to reset your password has been sent to your email.
    If you do not receive it within a reasonable amount of time, check your spam/junk folders.
    If it is not there ask your local administrator ." => "Odkaz na obnovenie hesla bol odoslaný na vašu emailovú adresu.
    Ak ho v krátkej dobe neobdržíte, skontrolujte si váš kôš a priečinok spam.
    Ak ho ani tam nenájdete, kontaktujte svojho administrátora.", "Request failed!
    Did you make sure your email/username was right?" => "Požiadavka zlyhala.
    Uistili ste sa, že vaše používateľské meno a email sú správne?", @@ -115,6 +123,8 @@ $TRANSLATIONS = array( "To login page" => "Na prihlasovaciu stránku", "New password" => "Nové heslo", "Reset password" => "Obnovenie hesla", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X nie je podporovaný a %s nebude správne fungovať na tejto platforme. Použite ho na vlastné riziko!", +"For the best results, please consider using a GNU/Linux server instead." => "Pre dosiahnutie najlepších výsledkov, prosím zvážte použitie GNU/Linux servera.", "Personal" => "Osobné", "Users" => "Používatelia", "Apps" => "Aplikácie", @@ -129,7 +139,7 @@ $TRANSLATIONS = array( "Error unfavoriting" => "Chyba pri odobratí z obľúbených", "Access forbidden" => "Prístup odmietnutý", "Cloud not found" => "Nenájdené", -"Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" => "Ahoj,\n\nchcem ti dať navedomie, že %s s tebou zdieľa %s.\nTu je odkaz: %s\n\n", +"Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" => "Dobrý deň,\n\nPoužívateľ %s zdieľa s vami súbor, alebo priečinok s názvom %s.\nPre zobrazenie kliknite na túto linku: %s\n", "The share will expire on %s." => "Zdieľanie expiruje %s.", "Cheers!" => "Pekný deň!", "Security Warning" => "Bezpečnostné varovanie", @@ -140,6 +150,7 @@ $TRANSLATIONS = array( "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Váš priečinok s dátami a súbormi je dostupný z internetu, lebo súbor .htaccess nefunguje.", "For information how to properly configure your server, please see the documentation." => "Pre informácie, ako správne nastaviť váš server, sa pozrite do dokumentácie.", "Create an admin account" => "Vytvoriť administrátorský účet", +"Storage & database" => "Úložislo & databáza", "Data folder" => "Priečinok dát", "Configure the database" => "Nastaviť databázu", "will be used" => "bude použité", @@ -162,6 +173,7 @@ $TRANSLATIONS = array( "remember" => "zapamätať", "Log in" => "Prihlásiť sa", "Alternative Logins" => "Alternatívne prihlásenie", +"Hey there,

    just letting you know that %s shared %s with you.
    View it!

    " => "Dobrý deň,

    Používateľ %s zdieľa s vami súbor, alebo priečinok s názvom »%s«.
    Pre zobrazenie kliknite na túto linku!

    ", "This ownCloud instance is currently in single user mode." => "Táto inštancia ownCloudu je teraz v jednopoužívateľskom móde.", "This means only administrators can use the instance." => "Len správca systému môže používať túto inštanciu.", "Contact your system administrator if this message persists or appeared unexpectedly." => "Kontaktujte prosím správcu systému, ak sa táto správa objavuje opakovane alebo neočakávane.", diff --git a/core/l10n/sl.php b/core/l10n/sl.php index 2cfdfd11899c88d5096b448a82f93f2a4bba7490..7476d9f9c7ce3a49b74a405d01f250a3da298a20 100644 --- a/core/l10n/sl.php +++ b/core/l10n/sl.php @@ -50,6 +50,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Napaka nalaganja predloge sporočil: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} spor datotek","{count} spora datotek","{count} spori datotek","{count} sporov datotek"), "One file conflict" => "En spor datotek", +"New Files" => "Nove datoteke", "Which files do you want to keep?" => "Katare datoteke želite ohraniti?", "If you select both versions, the copied file will have a number added to its name." => "Če izberete obe različici, bo kopirani datoteki k imenu dodana številka.", "Cancel" => "Prekliči", @@ -122,6 +123,8 @@ $TRANSLATIONS = array( "To login page" => "Na prijavno stran", "New password" => "Novo geslo", "Reset password" => "Ponastavi geslo", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Sistem Mac OS X ni podprt, zato %s ne bo deloval zanesljivo v tem okolju. Program uporabljate na lastno odgovornost! ", +"For the best results, please consider using a GNU/Linux server instead." => "Za najbolj še rezultate je priporočljivo uporabljati strežnik GNU/Linux.", "Personal" => "Osebno", "Users" => "Uporabniki", "Apps" => "Programi", diff --git a/core/l10n/sv.php b/core/l10n/sv.php index c4e92e621717cc530af457904f4d97fa0179e785..d46c204d7c356a78ae3fcf8263cf2d74f492bbb9 100644 --- a/core/l10n/sv.php +++ b/core/l10n/sv.php @@ -1,5 +1,6 @@ "Utgångsdatumet är i det förflutna.", "Couldn't send mail to following users: %s " => "Gick inte att skicka e-post till följande användare: %s", "Turned on maintenance mode" => "Aktiverade underhållsläge", "Turned off maintenance mode" => "Deaktiverade underhållsläge", @@ -49,6 +50,8 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Fel uppstod under inläsningen av meddelandemallen: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} filkonflikt","{count} filkonflikter"), "One file conflict" => "En filkonflikt", +"New Files" => "Nya filer", +"Already existing files" => "Filer som redan existerar", "Which files do you want to keep?" => "Vilken fil vill du behålla?", "If you select both versions, the copied file will have a number added to its name." => "Om du väljer båda versionerna kommer de kopierade filerna ha nummer tillagda i filnamnet.", "Cancel" => "Avbryt", @@ -56,6 +59,11 @@ $TRANSLATIONS = array( "(all selected)" => "(Alla valda)", "({count} selected)" => "({count} valda)", "Error loading file exists template" => "Fel uppstod filmall existerar", +"Very weak password" => "Väldigt svagt lösenord", +"Weak password" => "Svagt lösenord", +"So-so password" => "Okej lösenord", +"Good password" => "Bra lösenord", +"Strong password" => "Starkt lösenord", "Shared" => "Delad", "Share" => "Dela", "Error" => "Fel", @@ -99,9 +107,11 @@ $TRANSLATIONS = array( "Edit tags" => "Editera taggar", "Error loading dialog template: {error}" => "Fel under laddning utav dialog mall: {fel}", "No tags selected for deletion." => "Inga taggar valda för borttagning.", +"Please reload the page." => "Vänligen ladda om sidan.", "The update was unsuccessful. Please report this issue to the ownCloud community." => "Uppdateringen misslyckades. Rapportera detta problem till ownCloud Community.", "The update was successful. Redirecting you to ownCloud now." => "Uppdateringen lyckades. Du omdirigeras nu till OwnCloud.", "%s password reset" => "%s återställ lösenord", +"A problem has occurred whilst sending the email, please contact your administrator." => "Ett problem har uppstått under tiden e-post sändes, vänligen kontakta din administratör.", "Use the following link to reset your password: {link}" => "Använd följande länk för att återställa lösenordet: {link}", "The link to reset your password has been sent to your email.
    If you do not receive it within a reasonable amount of time, check your spam/junk folders.
    If it is not there ask your local administrator ." => "Länken för att återställa ditt lösenorden har skickats till din e-postadress
    Om du inte har erhållit meddelandet inom kort, vänligen kontrollera din skräppost-mapp
    Om den inte finns där, vänligen kontakta din administratör.", "Request failed!
    Did you make sure your email/username was right?" => "Begäran misslyckades!
    Är du helt säker på att din e-postadress/användarnamn är korrekt?", @@ -114,6 +124,8 @@ $TRANSLATIONS = array( "To login page" => "Till logginsidan", "New password" => "Nytt lösenord", "Reset password" => "Återställ lösenordet", +"Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " => "Mac OS X stöds inte och %s kommer inte att fungera korrekt på denna plattform. Använd på egen risk!", +"For the best results, please consider using a GNU/Linux server instead." => "För bästa resultat, överväg att använda en GNU/Linux server istället.", "Personal" => "Personligt", "Users" => "Användare", "Apps" => "Program", @@ -139,6 +151,7 @@ $TRANSLATIONS = array( "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." => "Din datakatalog och filer är förmodligen tillgängliga från Internet, eftersom .htaccess-filen inte fungerar.", "For information how to properly configure your server, please see the documentation." => "För information hur du korrekt konfigurerar din servern, se ownCloud dokumentationen.", "Create an admin account" => "Skapa ett administratörskonto", +"Storage & database" => "Lagring & databas", "Data folder" => "Datamapp", "Configure the database" => "Konfigurera databasen", "will be used" => "kommer att användas", @@ -149,6 +162,7 @@ $TRANSLATIONS = array( "Database host" => "Databasserver", "Finish setup" => "Avsluta installation", "Finishing …" => "Avslutar ...", +"This application requires JavaScript to be enabled for correct operation. Please enable JavaScript and re-load this interface." => "Denna applikation kräver JavaScript aktiverat för att fungera korrekt. Vänligen aktivera JavaScript och ladda om gränssnittet.", "%s is available. Get more information on how to update." => "%s är tillgänglig. Få mer information om hur du går tillväga för att uppdatera.", "Log out" => "Logga ut", "Automatic logon rejected!" => "Automatisk inloggning inte tillåten!", @@ -160,6 +174,9 @@ $TRANSLATIONS = array( "remember" => "kom ihåg", "Log in" => "Logga in", "Alternative Logins" => "Alternativa inloggningar", +"Hey there,

    just letting you know that %s shared %s with you.
    View it!

    " => "Hej där,

    ville bara informera dig om att %s delade %s med dig.
    Visa den!

    ", +"This ownCloud instance is currently in single user mode." => "Denna ownCloud instans är för närvarande i enanvändarläge", +"This means only administrators can use the instance." => "Detta betyder att endast administartörer kan använda instansen.", "Contact your system administrator if this message persists or appeared unexpectedly." => "Hör av dig till din system administratör ifall detta meddelande fortsätter eller visas oväntat.", "Thank you for your patience." => "Tack för ditt tålamod.", "Updating ownCloud to version %s, this may take a while." => "Uppdaterar ownCloud till version %s, detta kan ta en stund.", diff --git a/core/l10n/th_TH.php b/core/l10n/th_TH.php index 85a9b4ab2381fd8298c63ccb0fafa707977911ed..9ee3c60f947f913fd5022ccc33a5d2031fd3279b 100644 --- a/core/l10n/th_TH.php +++ b/core/l10n/th_TH.php @@ -37,6 +37,7 @@ $TRANSLATIONS = array( "No" => "ไม่ตกลง", "Ok" => "ตกลง", "_{count} file conflict_::_{count} file conflicts_" => array(""), +"New Files" => "ไฟล์ใหม่", "Cancel" => "ยกเลิก", "Shared" => "แชร์แล้ว", "Share" => "แชร์", diff --git a/core/l10n/tr.php b/core/l10n/tr.php index 03544cd3c0fb63fbd532450ef1180d295731c1c7..8f9c60c157b131b112ce51cd651907c11899c0bf 100644 --- a/core/l10n/tr.php +++ b/core/l10n/tr.php @@ -31,7 +31,7 @@ $TRANSLATIONS = array( "December" => "Aralık", "Settings" => "Ayarlar", "Saving..." => "Kaydediliyor...", -"seconds ago" => "saniye önce", +"seconds ago" => "saniyeler önce", "_%n minute ago_::_%n minutes ago_" => array("%n dakika önce","%n dakika önce"), "_%n hour ago_::_%n hours ago_" => array("%n saat önce","%n saat önce"), "today" => "bugün", @@ -42,7 +42,7 @@ $TRANSLATIONS = array( "months ago" => "ay önce", "last year" => "geçen yıl", "years ago" => "yıl önce", -"Choose" => "seç", +"Choose" => "Seç", "Error loading file picker template: {error}" => "Dosya seçici şablonu yüklenirken hata: {error}", "Yes" => "Evet", "No" => "Hayır", @@ -50,8 +50,10 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "İleti şablonu yüklenirken hata: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} dosya çakışması","{count} dosya çakışması"), "One file conflict" => "Bir dosya çakışması", +"New Files" => "Yeni Dosyalar", +"Already existing files" => "Zaten mevcut olan dosyalar", "Which files do you want to keep?" => "Hangi dosyaları saklamak istiyorsunuz?", -"If you select both versions, the copied file will have a number added to its name." => "Eğer iki sürümü de seçerseniz, kopyalanan dosya ismine eklenmiş bir sayı içerecektir.", +"If you select both versions, the copied file will have a number added to its name." => "İki sürümü de seçerseniz, kopyalanan dosyanın ismine bir sayı ilave edilecektir.", "Cancel" => "İptal", "Continue" => "Devam et", "(all selected)" => "(tümü seçildi)", @@ -65,7 +67,7 @@ $TRANSLATIONS = array( "Shared" => "Paylaşılan", "Share" => "Paylaş", "Error" => "Hata", -"Error while sharing" => "Paylaşım sırasında hata ", +"Error while sharing" => "Paylaşım sırasında hata", "Error while unsharing" => "Paylaşım iptal edilirken hata", "Error while changing permissions" => "İzinleri değiştirirken hata oluştu", "Shared with you and the group {group} by {owner}" => "{owner} tarafından sizinle ve {group} ile paylaştırılmış", @@ -111,7 +113,7 @@ $TRANSLATIONS = array( "%s password reset" => "%s parola sıfırlama", "A problem has occurred whilst sending the email, please contact your administrator." => "E-posta gönderilirken bir hata oluştu. Lütfen yönetinizle iletişime geçin.", "Use the following link to reset your password: {link}" => "Parolanızı sıfırlamak için bu bağlantıyı kullanın: {link}", -"The link to reset your password has been sent to your email.
    If you do not receive it within a reasonable amount of time, check your spam/junk folders.
    If it is not there ask your local administrator ." => "Parolanızı değiştirme bağlantısı e-posta adresinize gönderildi.
    Eğer makül bir süre içerisinde mesajı almadıysanız spam/junk dizinini kontrol ediniz.
    Eğer orada da bulamazsanız sistem yöneticinize sorunuz.", +"The link to reset your password has been sent to your email.
    If you do not receive it within a reasonable amount of time, check your spam/junk folders.
    If it is not there ask your local administrator ." => "Parolanızı değiştirme bağlantısı e-posta adresinize gönderildi.
    Eğer makül bir süre içerisinde mesajı almadıysanız spam/junk/gereksiz dizinini kontrol ediniz.
    Eğer yine bulamazsanız sistem yöneticinize sorunuz.", "Request failed!
    Did you make sure your email/username was right?" => "İstek başarısız!
    E-posta ve/veya kullanıcı adınızın doğru olduğundan emin misiniz?", "You will receive a link to reset your password via Email." => "Parolanızı sıfırlamak için bir bağlantıyı e-posta olarak alacaksınız.", "Username" => "Kullanıcı Adı", @@ -159,7 +161,7 @@ $TRANSLATIONS = array( "Database tablespace" => "Veritabanı tablo alanı", "Database host" => "Veritabanı sunucusu", "Finish setup" => "Kurulumu tamamla", -"Finishing …" => "Tamamlanıyor ..", +"Finishing …" => "Tamamlanıyor ...", "This application requires JavaScript to be enabled for correct operation. Please enable JavaScript and re-load this interface." => "Uygulama, doğru çalışabilmesi için JavaScript'in etkinleştirilmesini gerektiriyor. Lütfen JavaScript'i etkinleştirin ve bu arayüzü yeniden yükleyin.", "%s is available. Get more information on how to update." => "%s mevcut. Güncelleştirme hakkında daha fazla bilgi alın.", "Log out" => "Çıkış yap", diff --git a/core/l10n/uk.php b/core/l10n/uk.php index ade29981b49f8c05739841f628b5885709642747..f6bcfdcdc8de8b3dbd38fde10bb15c53750497aa 100644 --- a/core/l10n/uk.php +++ b/core/l10n/uk.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Помилка при завантаженні шаблону повідомлення: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} файловий конфлікт","{count} файлових конфліктів","{count} файлових конфліктів"), "One file conflict" => "Один файловий конфлікт", +"New Files" => "Нових Файлів", "Which files do you want to keep?" => "Які файли ви хочете залишити?", "If you select both versions, the copied file will have a number added to its name." => "Якщо ви оберете обидві версії, скопійований файл буде мати номер, доданий у його ім'я.", "Cancel" => "Відмінити", diff --git a/core/l10n/vi.php b/core/l10n/vi.php index be99580d9427075e3d4a11176db61356b837a5ca..319f68b6355f94fa9e6a44f96f6d8ea448a7d611 100644 --- a/core/l10n/vi.php +++ b/core/l10n/vi.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "Lỗi khi tải mẫu thông điệp: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} tập tin xung đột"), "One file conflict" => "Một tập tin xung đột", +"New Files" => "File mới", "Which files do you want to keep?" => "Bạn muốn tiếp tục với những tập tin nào?", "If you select both versions, the copied file will have a number added to its name." => "Nếu bạn chọn cả hai phiên bản, tập tin được sao chép sẽ được đánh thêm số vào tên của nó.", "Cancel" => "Hủy", diff --git a/core/l10n/zh_CN.php b/core/l10n/zh_CN.php index e5a6a254e547b384ad778057af3d24027bc6f8f3..68f50baf98f06192576aef22272b25dfce815d90 100644 --- a/core/l10n/zh_CN.php +++ b/core/l10n/zh_CN.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "加载消息模板出错: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} 个文件冲突"), "One file conflict" => "1个文件冲突", +"New Files" => "新文件", "Which files do you want to keep?" => "想要保留哪一个文件呢?", "If you select both versions, the copied file will have a number added to its name." => "如果同时选择了连个版本,复制的文件名将会添加上一个数字。", "Cancel" => "取消", diff --git a/core/l10n/zh_TW.php b/core/l10n/zh_TW.php index dae143cef40b07da895d85794022de73616be1d6..0799344697a2c09effac87269e921c463bbc2671 100644 --- a/core/l10n/zh_TW.php +++ b/core/l10n/zh_TW.php @@ -49,6 +49,7 @@ $TRANSLATIONS = array( "Error loading message template: {error}" => "載入訊息樣板出錯: {error}", "_{count} file conflict_::_{count} file conflicts_" => array("{count} 個檔案衝突"), "One file conflict" => "一個檔案衝突", +"New Files" => "新檔案", "Which files do you want to keep?" => "您要保留哪一個檔案?", "If you select both versions, the copied file will have a number added to its name." => "如果您同時選擇兩個版本,被複製的那個檔案名稱後面會加上編號", "Cancel" => "取消", diff --git a/core/lostpassword/templates/resetpassword.php b/core/lostpassword/templates/resetpassword.php index 0ab32acca6012d5484b3d97d129c4776044ed316..881455f5a9dd535741f385e7d5b057a8128549b6 100644 --- a/core/lostpassword/templates/resetpassword.php +++ b/core/lostpassword/templates/resetpassword.php @@ -1,14 +1,14 @@ -
    +
    -

    t('Your password was reset'); ?>

    -

    t('To login page'); ?>

    +

    t('Your password was reset')); ?>

    +

    t('To login page')); ?>

    - +

    - +
    diff --git a/core/setup/controller.php b/core/setup/controller.php index bb9c9101fe29a22d2a5c41bde836f7b85c474baf..1a8e9b2b764ade3b7d7a0a0cf532fe970ac5dd9d 100644 --- a/core/setup/controller.php +++ b/core/setup/controller.php @@ -20,7 +20,7 @@ class Controller { $errors = array('errors' => $e); if(count($e) > 0) { - $options = array_merge($post, $opts, $errors); + $options = array_merge($opts, $post, $errors); $this->display($options); } else { @@ -28,7 +28,8 @@ class Controller { } } else { - $this->display($opts); + $options = array_merge($opts, $post); + $this->display($options); } } @@ -41,6 +42,7 @@ class Controller { 'dbname' => '', 'dbtablespace' => '', 'dbhost' => '', + 'dbtype' => '', ); $parameters = array_merge($defaults, $post); diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php index 91157b923a5cdc57b954888bc456d834212976bc..5788d1d5bd3aa60f3432b26f75e6d150fed1fc4a 100644 --- a/core/templates/layout.guest.php +++ b/core/templates/layout.guest.php @@ -36,7 +36,7 @@
    diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index 3d89750348073ee79458d2017436f53c258eb89c..ba5f6ef9b541ae7f9705925ac49e05b84e990969 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -15,7 +15,7 @@ - + @@ -46,7 +46,7 @@
    -
    +

    t('Setup Warning'));?>

    @@ -79,42 +79,42 @@ if (!$_['isWebDavWorking']) { t('Please double check the installation guides.', link_to_docs('admin-install'))); ?> -
    +
    -
    +

    t('Module \'fileinfo\' missing'));?>

    t('The PHP module \'fileinfo\' is missing. We strongly recommend to enable this module to get best results with mime-type detection.')); ?> -
    +
    -
    +

    t('Your PHP version is outdated'));?>

    t('Your PHP version is outdated. We strongly recommend to update to 5.3.8 or newer because older versions are known to be broken. It is possible that this installation is not working correctly.')); ?> -
    +
    -
    +

    t('Locale not working'));?>

    @@ -132,21 +132,21 @@ if (!$_['isLocaleWorking']) { ?> -
    +
    -
    +

    t('Internet connection not working'));?>

    t('This server has no working internet connection. This means that some of the features like mounting of external storage, notifications about updates or installation of 3rd party apps don´t work. Accessing files from remote and sending of notification emails might also not work. We suggest to enable internet connection for this server if you want to have all features.')); ?> -
    + @@ -156,7 +156,7 @@ if (!$_['internetconnectionworking']) { } ;?> -
    +

    t('Cron'));?>

    @@ -199,9 +199,9 @@ if (!$_['internetconnectionworking']) {
    t("Use systems cron service to call the cron.php file every 15 minutes.")); ?>

    -
    + -
    +

    t('Sharing'));?>

    @@ -255,9 +255,9 @@ if (!$_['internetconnectionworking']) {
    -
    + -
    +

    t('Security'));?>

    @@ -288,9 +288,9 @@ if (!$_['internetconnectionworking']) {
    -
    + -
    +

    t('Email Server'));?>

    t('This is used for sending out notifications.')); ?>

    @@ -370,9 +370,9 @@ if (!$_['internetconnectionworking']) { t( 'Test email settings' )); ?> -
    + -
    +

    t('Log'));?>

    t('Log level'));?> - - - -
    -
    -
    +
    +

    t('Password'));?>

    +
    t('Your password was changed');?>
    +
    t('Unable to change your password');?>
    + + + + +
    +
    -
    -
    -

    t('Full Name');?>

    - - - -
    + +

    t('Full Name');?>

    + + +
    -
    -
    -

    t('Email'));?>

    - -
    - t('Fill in an email address to enable password recovery and receive notifications'));?> -
    + +

    t('Email'));?>

    + +
    + t('Fill in an email address to enable password recovery and receive notifications'));?>
    -
    -
    -

    t('Profile picture')); ?>

    -
    -

    - - -
    t('Upload new')); ?>
    - -
    t('Select new from Files')); ?>
    -
    t('Remove image')); ?>

    - t('Either png or jpg. Ideally square but you will be able to crop it.')); ?> - - t('Your avatar is provided by your original account.')); ?> - -
    - -
    + +

    t('Profile picture')); ?>

    +
    +

    + + +
    t('Upload new')); ?>
    + +
    t('Select new from Files')); ?>
    +
    t('Remove image')); ?>

    + t('Either png or jpg. Ideally square but you will be able to crop it.')); ?> + + t('Your avatar is provided by your original account.')); ?> + +
    +
    -
    -
    -

    t('Language'));?>

    - + + + - - - - - - - - - - - t('Help translate'));?> - - -
    + + + + + + + + + t('Help translate'));?> + +
    -
    +

    t('WebDAV'));?>


    t('Use this address to access your Files via WebDAV', array(link_to_docs('user-webdav'))));?> -
    + -
    +

    t( 'Encryption' ) ); ?>

    @@ -174,18 +164,17 @@ if($_['passwordChangeSupported']) {


    -
    + -
    +

    t('Version'));?>

    getName()); ?>
    t('Developed by the ownCloud community, the source code is licensed under the AGPL.')); ?> -
    - + + + diff --git a/settings/users.php b/settings/users.php index 2f1c63a0b59856900109f277c0ff93e5aa3366bd..f09d0e90d3c6bde5265a085450163153af0db743 100644 --- a/settings/users.php +++ b/settings/users.php @@ -6,7 +6,6 @@ */ OC_Util::checkSubAdminUser(); -OC_App::loadApps(); // We have some javascript foo! OC_Util::addScript( 'settings', 'users' ); diff --git a/status.php b/status.php index 88422100f14cf96afb6b637ecb139520efa8807e..861eaed9cd2638c3fe8ca3099d9f4ae811bb3981 100644 --- a/status.php +++ b/status.php @@ -21,8 +21,6 @@ * */ -$RUNTIME_NOAPPS = true; //no apps, yet - try { require_once 'lib/base.php'; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 70de7cd1c44a20112d5769f763f54251f97b8cb9..99374d68a5c59971215144727ddb9fe65c55c2b0 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -16,3 +16,4 @@ if (!class_exists('PHPUnit_Framework_TestCase')) { OC_Hook::clear(); OC_Log::$enabled = false; +OC_FileProxy::clearProxies(); diff --git a/tests/data/lorem-big.txt b/tests/data/lorem-big.txt new file mode 100644 index 0000000000000000000000000000000000000000..3712b9d30f017d742a954b2af33a42722990695c --- /dev/null +++ b/tests/data/lorem-big.txt @@ -0,0 +1,29 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse id hendrerit felis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed dictum dolor nec lobortis sagittis. Aliquam blandit lobortis ullamcorper. Donec malesuada ante ante, vel cursus purus suscipit ut. Sed a eros vitae lorem tristique hendrerit a a odio. Cras interdum mi lectus, sed molestie mauris tempus sit amet. Praesent auctor neque venenatis diam tincidunt sodales. Maecenas tincidunt ligula et ipsum dignissim, et molestie dui hendrerit. Nunc lobortis mauris vel tempor tristique. Sed consectetur bibendum nunc. Pellentesque augue velit, interdum ac posuere eu, eleifend et massa. Vestibulum ac mi eu mi viverra iaculis. Sed consequat leo adipiscing dui varius, sagittis vestibulum massa vehicula. + +Praesent imperdiet erat vitae dui placerat, sit amet vulputate tortor viverra. In laoreet elit lorem, at luctus est tempor ac. Nam elementum scelerisque nisl vitae accumsan. Curabitur cursus rutrum est, ut adipiscing ante elementum ut. Ut lectus sem, luctus ut massa non, dignissim vestibulum ipsum. Suspendisse non convallis enim, aliquam adipiscing velit. Donec pharetra non turpis hendrerit porttitor. Aliquam erat volutpat. + +Cras eget arcu eu dolor faucibus accumsan non eget orci. Integer quis quam tincidunt, faucibus neque in, imperdiet lacus. Aenean dui turpis, lacinia quis ligula non, semper adipiscing tellus. Curabitur vitae dui quis nisl malesuada commodo. Nunc eleifend metus enim, eu aliquet dui semper sit amet. Sed a odio sapien. Suspendisse vitae ante id sapien semper accumsan. Sed vestibulum erat quis laoreet pellentesque. Nullam placerat ligula eu odio faucibus, eget dictum orci tristique. Quisque sit amet pulvinar velit, lacinia dictum sem. + +Phasellus id sagittis lacus. Vivamus facilisis convallis metus, sit amet ultricies purus gravida quis. Vivamus eget egestas arcu, a euismod risus. Fusce metus arcu, molestie ut lacinia at, commodo eu nibh. In leo tortor, feugiat aliquet semper in, malesuada ac nulla. Fusce tempor ultricies blandit. Pellentesque et lorem quam. Suspendisse eros eros, mattis ut porttitor vitae, fermentum eget augue. Aliquam vitae justo sed est dictum lobortis. Cras lacinia commodo ligula sed ornare. Donec ut eros semper, sodales tellus quis, cursus quam. Quisque elementum ullamcorper pellentesque. Integer in rutrum ante, vel condimentum metus. Aliquam erat volutpat. + +Quisque convallis tempus eros, sit amet mattis ipsum eleifend in. Mauris volutpat, urna ut commodo tempus, est quam scelerisque erat, eget consequat nulla arcu id eros. Nam elementum nibh quis tincidunt adipiscing. Fusce tristique pretium mollis. Nulla quis ornare felis, vel lacinia diam. In et dui et mauris vestibulum commodo. In hac habitasse platea dictumst. Vestibulum viverra pellentesque tortor, tempor vehicula orci. Praesent rutrum turpis ipsum, ac commodo nisi vehicula ac. + +Nulla gravida ultrices mauris. Ut congue purus nec dolor euismod, vitae auctor elit condimentum. Nullam elementum velit lectus, fringilla pharetra sem hendrerit sit amet. Cras quis lobortis nisi, id interdum massa. Proin eget porttitor sapien. Vivamus quam odio, consectetur at rhoncus vel, posuere in nisi. Donec hendrerit urna ac massa tristique, pellentesque consequat orci dapibus. Mauris mi erat, aliquet id adipiscing ultricies, ultrices nec lacus. Proin imperdiet elit magna, ut suscipit metus faucibus eget. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas at leo lorem. Donec mi nibh, blandit ut mi quis, dictum adipiscing ante. Curabitur sodales blandit odio id viverra. Fusce sagittis rutrum nibh. Mauris risus lacus, placerat at dictum in, varius volutpat quam. + +Ut accumsan tincidunt dui, non semper lorem sodales nec. Curabitur pellentesque velit nec erat ultrices, in convallis diam suscipit. Curabitur pellentesque convallis mi. Phasellus iaculis orci quis nisi semper auctor. Vestibulum eleifend tortor quis odio feugiat, pulvinar congue turpis blandit. Sed viverra diam risus, vel mattis orci dignissim ut. Cras pellentesque dapibus dolor. Morbi tempor eleifend magna. Ut sodales ut sapien sed elementum. In hac habitasse platea dictumst. + +Nullam eget sagittis tellus. Donec a tellus id ligula viverra pellentesque. Pellentesque nulla turpis, pretium vel sem vel, placerat ultricies diam. Donec felis nibh, rhoncus id ornare at, lobortis vel massa. Nullam eu luctus ipsum. Mauris consequat dictum aliquam. Suspendisse ullamcorper aliquam mauris, viverra tincidunt augue suscipit at. Sed luctus scelerisque justo ut semper. Phasellus massa mauris, molestie at nulla eget, dictum ultricies nisi. Aliquam rhoncus nisl sed urna egestas, vel luctus lectus euismod. Mauris sagittis dapibus leo. Donec vitae dignissim risus, ac ultricies augue. Ut vulputate tortor sed dui consectetur placerat. Nullam viverra non diam vel dignissim. + +Suspendisse potenti. Integer facilisis neque vitae euismod adipiscing. Aenean dictum leo commodo dui sodales, sit amet volutpat mauris gravida. Proin tempus convallis eros at consectetur. Proin nisl purus, dictum vel euismod ut, imperdiet quis est. Etiam sollicitudin lobortis neque eget pulvinar. Etiam venenatis vel sem ut posuere. Aliquam consectetur rhoncus facilisis. Morbi a viverra orci. + +Praesent ut vehicula orci, vel convallis risus. Suspendisse consectetur varius interdum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin vel sodales enim. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur suscipit tristique justo vel dapibus. Sed tincidunt mattis massa a auctor. Donec in tincidunt elit. Curabitur interdum neque at ante fringilla tempus. In hac habitasse platea dictumst. Vivamus luctus ligula ut nisl fermentum egestas. Praesent pulvinar accumsan neque. Sed nec leo sit amet arcu vehicula vehicula non ac diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; + +Morbi vel arcu quis neque dictum ullamcorper. Pellentesque condimentum consequat lacinia. Vestibulum eleifend placerat erat, eu hendrerit dui pulvinar eget. Vestibulum accumsan, lectus id vehicula fringilla, erat eros dictum massa, ut tristique libero mi eu ante. In at ante nunc. Praesent sodales ullamcorper porta. Curabitur egestas odio elit. Praesent et libero malesuada, venenatis lorem vitae, eleifend nisl. Donec dapibus euismod turpis, nec porttitor turpis dapibus ac. Fusce iaculis lacus eget dictum aliquam. Sed dictum eu enim ac posuere. Ut accumsan, ipsum et laoreet consectetur, ipsum quam dapibus diam, ac molestie ligula dui id massa. Nulla aliquam mauris congue nibh vestibulum imperdiet. + +Aenean ultricies, orci vel consectetur suscipit, ante nisi eleifend est, vitae suscipit risus erat dictum dui. Ut nisi diam, tristique sed nisl nec, aliquam gravida orci. Vestibulum in molestie sem. Ut eu molestie mi. Suspendisse potenti. Nunc sagittis lorem ut est vehicula, vitae imperdiet leo rutrum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec pharetra urna pretium, faucibus orci cursus, sodales purus. Duis iaculis dignissim augue, non aliquet ligula elementum quis. Sed tempus a nisi et faucibus. Donec mattis ligula ac sem aliquam, sed sodales est ullamcorper. Cras vel orci est. Integer eget ultricies nisi. + +Quisque rhoncus, nisl vel auctor consectetur, sapien augue iaculis urna, quis suscipit arcu dolor ac est. Fusce sit amet quam lacinia, malesuada lorem vitae, dapibus justo. Mauris eget massa nec dolor volutpat tempor ut eu ante. Donec risus mi, aliquam at euismod vulputate, ullamcorper non leo. Etiam ac elit velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus sollicitudin enim sed felis pharetra, a convallis mi venenatis. Donec convallis non velit venenatis suscipit. Sed massa risus, dictum quis aliquam ut, placerat quis arcu. Donec at nisi neque. Nullam porta et mi vel ultricies. Donec vel aliquam sem. Mauris varius, ipsum interdum mattis rhoncus, nunc nisl vehicula tortor, quis condimentum nibh nisl vel ante. Sed vel pretium dui. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce pulvinar molestie neque, quis luctus ante. + +Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec ac ipsum egestas, luctus urna aliquet, fringilla tortor. Cras eleifend sed tellus tempor congue. Integer venenatis magna dignissim pharetra cursus. Nulla volutpat, sem sit amet malesuada laoreet, odio libero consectetur orci, sit amet pellentesque neque ligula quis libero. Morbi nec interdum metus, in imperdiet justo. Fusce euismod egestas nulla et elementum. Etiam aliquam lectus quis eros semper, sed dapibus velit ultrices. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Proin sed elit vel massa placerat mattis et vel mauris. Aliquam accumsan ante ligula, at accumsan enim pellentesque sit amet. Sed eget quam vel nunc molestie iaculis vitae nec massa. Vivamus sed accumsan libero. Duis pretium quam at blandit sollicitudin. Nullam sodales sit amet elit ac adipiscing. Ut ullamcorper dignissim sapien. Nulla facilisi. Fusce sed consequat lectus, et tempus ipsum. Aliquam vestibulum lectus vitae quam mollis, et adipiscing nisl lobortis diff --git a/tests/karma.config.js b/tests/karma.config.js index 529bd31338fe6e8492c3fa22e36c07e979a22f37..338e3f868e98b744de299b94ddabd1731caa694b 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -121,6 +121,9 @@ module.exports = function(config) { files.push('apps/' + appsToTest[i] + '/tests/js/*.js'); } + // serve images to avoid warnings + files.push({pattern: 'core/img/**/*', watched: false, included: false, served: true}); + config.set({ // base path, that will be used to resolve files and exclude @@ -137,6 +140,11 @@ module.exports = function(config) { ], + proxies: { + // prevent warnings for images + '/context.html//core/img/': 'http://localhost:9876/base/core/img/' + }, + // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['dots', 'junit', 'coverage'], @@ -167,7 +175,7 @@ module.exports = function(config) { logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file changes - autoWatch: false, + autoWatch: true, // Start these browsers, currently available: // - Chrome diff --git a/tests/lib/api.php b/tests/lib/api.php index 233beebd68a8551964fd1f1d5434ef28a4111c29..0f7d08543ea51a8121d7bbc47e1fa1ce6850e1e5 100644 --- a/tests/lib/api.php +++ b/tests/lib/api.php @@ -37,7 +37,7 @@ class Test_API extends PHPUnit_Framework_TestCase { function dataProviderTestOneResult() { return array( array(100, true), - array(101, true), + array(101, false), array(997, false), ); } diff --git a/tests/lib/appframework/dependencyinjection/DIContainerTest.php b/tests/lib/appframework/dependencyinjection/DIContainerTest.php index f3ebff0207f38a9fda87495debed6ba3cba444de..d1bc900fb28bfa82a55cc97d810f8a0f20c1806d 100644 --- a/tests/lib/appframework/dependencyinjection/DIContainerTest.php +++ b/tests/lib/appframework/dependencyinjection/DIContainerTest.php @@ -70,7 +70,7 @@ class DIContainerTest extends \PHPUnit_Framework_TestCase { public function testMiddlewareDispatcherIncludesSecurityMiddleware(){ - $this->container['Request'] = new Request(); + $this->container['Request'] = new Request(array('method' => 'GET')); $security = $this->container['SecurityMiddleware']; $dispatcher = $this->container['MiddlewareDispatcher']; diff --git a/tests/lib/appframework/http/JSONResponseTest.php b/tests/lib/appframework/http/JSONResponseTest.php index 534c54cbcee726f473c1b55d59162d95b20e01bb..b9b7c7d63823e18b077375d4ef171f9192c05fd6 100644 --- a/tests/lib/appframework/http/JSONResponseTest.php +++ b/tests/lib/appframework/http/JSONResponseTest.php @@ -28,6 +28,7 @@ namespace OC\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http; //require_once(__DIR__ . "/../classloader.php"); @@ -95,4 +96,13 @@ class JSONResponseTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($code, $response->getStatus()); } + public function testChainability() { + $params = array('hi', 'yo'); + $this->json->setData($params) + ->setStatus(Http::STATUS_NOT_FOUND); + + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->json->getStatus()); + $this->assertEquals(array('hi', 'yo'), $this->json->getData()); + } + } diff --git a/tests/lib/appframework/http/RequestTest.php b/tests/lib/appframework/http/RequestTest.php index 00473a8c44f9167827592591d6df7e6847cd8216..58828d17bb2ab7c00d6dd7f738b89d59216bc619 100644 --- a/tests/lib/appframework/http/RequestTest.php +++ b/tests/lib/appframework/http/RequestTest.php @@ -18,6 +18,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { stream_wrapper_unregister('fakeinput'); } stream_wrapper_register('fakeinput', 'RequestStream'); + $this->stream = 'fakeinput://data'; } public function tearDown() { @@ -30,7 +31,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'method' => 'GET', ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); // Countable $this->assertEquals(2, count($request)); @@ -54,9 +55,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), 'post' => array('name' => 'Jane Doe', 'nickname' => 'Janey'), 'urlParams' => array('user' => 'jw', 'name' => 'Johnny Weissmüller'), + 'method' => 'GET' ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals(3, count($request)); $this->assertEquals('Janey', $request->{'nickname'}); @@ -70,9 +72,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase { public function testImmutableArrayAccess() { $vars = array( 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), + 'method' => 'GET' ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $request['nickname'] = 'Janey'; } @@ -82,9 +85,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase { public function testImmutableMagicAccess() { $vars = array( 'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'), + 'method' => 'GET' ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $request->{'nickname'} = 'Janey'; } @@ -97,7 +101,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'method' => 'GET', ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $result = $request->post; } @@ -107,7 +111,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'method' => 'GET', ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals('GET', $request->method); $result = $request->get; $this->assertEquals('John Q. Public', $result['name']); @@ -119,10 +123,10 @@ class RequestTest extends \PHPUnit_Framework_TestCase { $data = '{"name": "John Q. Public", "nickname": "Joey"}'; $vars = array( 'method' => 'POST', - 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'), + 'server' => array('CONTENT_TYPE' => 'application/json; utf-8') ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals('POST', $request->method); $result = $request->post; $this->assertEquals('John Q. Public', $result['name']); @@ -140,7 +144,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'server' => array('CONTENT_TYPE' => 'application/x-www-form-urlencoded'), ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals('PATCH', $request->method); $result = $request->patch; @@ -159,7 +163,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'), ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals('PUT', $request->method); $result = $request->put; @@ -174,7 +178,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'server' => array('CONTENT_TYPE' => 'application/json; utf-8'), ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals('PATCH', $request->method); $result = $request->patch; @@ -193,7 +197,7 @@ class RequestTest extends \PHPUnit_Framework_TestCase { 'server' => array('CONTENT_TYPE' => 'image/png'), ); - $request = new Request($vars); + $request = new Request($vars, $this->stream); $this->assertEquals('PUT', $request->method); $resource = $request->put; $contents = stream_get_contents($resource); diff --git a/tests/lib/appframework/http/ResponseTest.php b/tests/lib/appframework/http/ResponseTest.php index 063ab8b5d33bc8e591fb855ec520aca4c1412610..27350725d79a76921e65acf9a5043fce713eca6d 100644 --- a/tests/lib/appframework/http/ResponseTest.php +++ b/tests/lib/appframework/http/ResponseTest.php @@ -117,5 +117,25 @@ class ResponseTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('Thu, 01 Jan 1970 00:00:01 +0000', $headers['Last-Modified']); } + public function testChainability() { + $lastModified = new \DateTime(null, new \DateTimeZone('GMT')); + $lastModified->setTimestamp(1); + + $this->childResponse->setEtag('hi') + ->setStatus(Http::STATUS_NOT_FOUND) + ->setLastModified($lastModified) + ->cacheFor(33) + ->addHeader('hello', 'world'); + + $headers = $this->childResponse->getHeaders(); + + $this->assertEquals('world', $headers['hello']); + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->childResponse->getStatus()); + $this->assertEquals('hi', $this->childResponse->getEtag()); + $this->assertEquals('Thu, 01 Jan 1970 00:00:01 +0000', $headers['Last-Modified']); + $this->assertEquals('max-age=33, must-revalidate', + $headers['Cache-Control']); + + } } diff --git a/tests/lib/appframework/http/TemplateResponseTest.php b/tests/lib/appframework/http/TemplateResponseTest.php index a583d9da14f538797557dc3a9034148e75b713a0..0b158edff6f9392460dbd14ce15c24137abba2b0 100644 --- a/tests/lib/appframework/http/TemplateResponseTest.php +++ b/tests/lib/appframework/http/TemplateResponseTest.php @@ -25,6 +25,7 @@ namespace OC\AppFramework\Http; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Http; class TemplateResponseTest extends \PHPUnit_Framework_TestCase { @@ -98,4 +99,13 @@ class TemplateResponseTest extends \PHPUnit_Framework_TestCase { $this->assertEquals($render, $this->tpl->getRenderAs()); } + public function testChainability() { + $params = array('hi' => 'yo'); + $this->tpl->setParams($params) + ->setStatus(Http::STATUS_NOT_FOUND); + + $this->assertEquals(Http::STATUS_NOT_FOUND, $this->tpl->getStatus()); + $this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams()); + } + } diff --git a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php index f16b14150c34a9a18c45255918feba42bbe4e20e..935f97d2a6f251630d6d813b0298bd35189b54e3 100644 --- a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php +++ b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php @@ -132,7 +132,7 @@ class MiddlewareDispatcherTest extends \PHPUnit_Framework_TestCase { private function getControllerMock(){ return $this->getMock('OCP\AppFramework\Controller', array('method'), - array($this->getAPIMock(), new Request())); + array($this->getAPIMock(), new Request(array('method' => 'GET')))); } diff --git a/tests/lib/appframework/routing/RoutingTest.php b/tests/lib/appframework/routing/RoutingTest.php index 9f2675bf0b459d5963e12eec03798ab1f930407d..261ab0b26af759d3c7f521b26fe13bbc34c03b4a 100644 --- a/tests/lib/appframework/routing/RoutingTest.php +++ b/tests/lib/appframework/routing/RoutingTest.php @@ -36,6 +36,16 @@ class RouteConfigTest extends \PHPUnit_Framework_TestCase $this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open'); } + public function testSimpleRouteWithRequirements() + { + $routes = array('routes' => array( + array('name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'requirements' => array('something')) + )); + + $this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array('something')); + } + + /** * @expectedException \UnexpectedValueException */ @@ -85,10 +95,10 @@ class RouteConfigTest extends \PHPUnit_Framework_TestCase * @param string $controllerName * @param string $actionName */ - private function assertSimpleRoute($routes, $name, $verb, $url, $controllerName, $actionName) + private function assertSimpleRoute($routes, $name, $verb, $url, $controllerName, $actionName, array $requirements=array()) { // route mocks - $route = $this->mockRoute($verb, $controllerName, $actionName); + $route = $this->mockRoute($verb, $controllerName, $actionName, $requirements); // router mock $router = $this->getMock("\OC\Route\Router", array('create')); @@ -166,15 +176,15 @@ class RouteConfigTest extends \PHPUnit_Framework_TestCase } /** - * @param $verb - * @param $controllerName - * @param $actionName + * @param string $verb + * @param string $controllerName + * @param string $actionName * @return \PHPUnit_Framework_MockObject_MockObject */ - private function mockRoute($verb, $controllerName, $actionName) + private function mockRoute($verb, $controllerName, $actionName, array $requirements=array()) { $container = new DIContainer('app1'); - $route = $this->getMock("\OC\Route\Route", array('method', 'action'), array(), '', false); + $route = $this->getMock("\OC\Route\Route", array('method', 'action', 'requirements'), array(), '', false); $route ->expects($this->exactly(1)) ->method('method') @@ -186,6 +196,14 @@ class RouteConfigTest extends \PHPUnit_Framework_TestCase ->method('action') ->with($this->equalTo(new RouteActionHandler($container, $controllerName, $actionName))) ->will($this->returnValue($route)); + + if(count($requirements) > 0) { + $route + ->expects($this->exactly(1)) + ->method('requirements') + ->with($this->equalTo($requirements)) + ->will($this->returnValue($route)); + } return $route; } diff --git a/tests/lib/dbschema.php b/tests/lib/dbschema.php index 11e9fcdf4fa9a5b4505a7446046420c5abe32b98..cfa2d6fd9aab0b7247798a79a24ccfe639719a79 100644 --- a/tests/lib/dbschema.php +++ b/tests/lib/dbschema.php @@ -71,6 +71,9 @@ class Test_DBSchema extends PHPUnit_Framework_TestCase { $this->assertTableNotExist($this->table2); } + /** + * @param string $table + */ public function tableExist($table) { switch (OC_Config::getValue( 'dbtype', 'sqlite' )) { diff --git a/tests/lib/files/filesystem.php b/tests/lib/files/filesystem.php index 90f1dfe581b12674d3169c6fa66242e54ae876ac..53f528af793db009a4b1bfc5b4ecbd543c974fde 100644 --- a/tests/lib/files/filesystem.php +++ b/tests/lib/files/filesystem.php @@ -226,4 +226,55 @@ class Filesystem extends \PHPUnit_Framework_TestCase { $path = $arguments['path']; $this->assertEquals($path, \OC\Files\Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized } + + /** + * Test that the default cache dir is part of the user's home + */ + public function testMountDefaultCacheDir() { + $userId = uniqid('user_'); + $oldCachePath = \OC_Config::getValue('cache_path', ''); + // no cache path configured + \OC_Config::setValue('cache_path', ''); + + \OC_User::createUser($userId, $userId); + \OC\Files\Filesystem::initMountPoints($userId); + + $this->assertEquals( + '/' . $userId . '/', + \OC\Files\Filesystem::getMountPoint('/' . $userId . '/cache') + ); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath('/' . $userId . '/cache'); + $this->assertInstanceOf('\OC\Files\Storage\Home', $storage); + $this->assertEquals('cache', $internalPath); + \OC_User::deleteUser($userId); + + \OC_Config::setValue('cache_path', $oldCachePath); + } + + /** + * Test that an external cache is mounted into + * the user's home + */ + public function testMountExternalCacheDir() { + $userId = uniqid('user_'); + + $oldCachePath = \OC_Config::getValue('cache_path', ''); + // set cache path to temp dir + $cachePath = \OC_Helper::tmpFolder() . '/extcache'; + \OC_Config::setValue('cache_path', $cachePath); + + \OC_User::createUser($userId, $userId); + \OC\Files\Filesystem::initMountPoints($userId); + + $this->assertEquals( + '/' . $userId . '/cache/', + \OC\Files\Filesystem::getMountPoint('/' . $userId . '/cache') + ); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath('/' . $userId . '/cache'); + $this->assertInstanceOf('\OC\Files\Storage\Local', $storage); + $this->assertEquals('', $internalPath); + \OC_User::deleteUser($userId); + + \OC_Config::setValue('cache_path', $oldCachePath); + } } diff --git a/tests/lib/files/storage/storage.php b/tests/lib/files/storage/storage.php index f9291758606dc3cb327ac459ef264c9f1ca822d5..38cd17ac8c94e09138be61600335622eeba10096 100644 --- a/tests/lib/files/storage/storage.php +++ b/tests/lib/files/storage/storage.php @@ -64,17 +64,17 @@ abstract class Storage extends \PHPUnit_Framework_TestCase { * @dataProvider directoryProvider */ public function testDirectories($directory) { - $this->assertFalse($this->instance->file_exists('/'.$directory)); + $this->assertFalse($this->instance->file_exists('/' . $directory)); - $this->assertTrue($this->instance->mkdir('/'.$directory)); + $this->assertTrue($this->instance->mkdir('/' . $directory)); - $this->assertTrue($this->instance->file_exists('/'.$directory)); - $this->assertTrue($this->instance->is_dir('/'.$directory)); - $this->assertFalse($this->instance->is_file('/'.$directory)); - $this->assertEquals('dir', $this->instance->filetype('/'.$directory)); - $this->assertEquals(0, $this->instance->filesize('/'.$directory)); - $this->assertTrue($this->instance->isReadable('/'.$directory)); - $this->assertTrue($this->instance->isUpdatable('/'.$directory)); + $this->assertTrue($this->instance->file_exists('/' . $directory)); + $this->assertTrue($this->instance->is_dir('/' . $directory)); + $this->assertFalse($this->instance->is_file('/' . $directory)); + $this->assertEquals('dir', $this->instance->filetype('/' . $directory)); + $this->assertEquals(0, $this->instance->filesize('/' . $directory)); + $this->assertTrue($this->instance->isReadable('/' . $directory)); + $this->assertTrue($this->instance->isUpdatable('/' . $directory)); $dh = $this->instance->opendir('/'); $content = array(); @@ -85,13 +85,13 @@ abstract class Storage extends \PHPUnit_Framework_TestCase { } $this->assertEquals(array($directory), $content); - $this->assertFalse($this->instance->mkdir('/'.$directory)); //cant create existing folders - $this->assertTrue($this->instance->rmdir('/'.$directory)); + $this->assertFalse($this->instance->mkdir('/' . $directory)); //cant create existing folders + $this->assertTrue($this->instance->rmdir('/' . $directory)); $this->wait(); - $this->assertFalse($this->instance->file_exists('/'.$directory)); + $this->assertFalse($this->instance->file_exists('/' . $directory)); - $this->assertFalse($this->instance->rmdir('/'.$directory)); //cant remove non existing folders + $this->assertFalse($this->instance->rmdir('/' . $directory)); //cant remove non existing folders $dh = $this->instance->opendir('/'); $content = array(); @@ -103,8 +103,7 @@ abstract class Storage extends \PHPUnit_Framework_TestCase { $this->assertEquals(array(), $content); } - public function directoryProvider() - { + public function directoryProvider() { return array( array('folder'), array(' folder'), @@ -113,11 +112,23 @@ abstract class Storage extends \PHPUnit_Framework_TestCase { array('spéciäl földer'), ); } + + function loremFileProvider() { + $root = \OC::$SERVERROOT . '/tests/data/'; + return array( + // small file + array($root . 'lorem.txt'), + // bigger file (> 8 KB which is the standard PHP block size) + array($root . 'lorem-big.txt') + ); + } + /** * test the various uses of file_get_contents and file_put_contents + * + * @dataProvider loremFileProvider */ - public function testGetPutContents() { - $sourceFile = \OC::$SERVERROOT . '/tests/data/lorem.txt'; + public function testGetPutContents($sourceFile) { $sourceText = file_get_contents($sourceFile); //fill a file with string data @@ -298,4 +309,40 @@ abstract class Storage extends \PHPUnit_Framework_TestCase { $this->assertFalse($this->instance->file_exists('folder/bar')); $this->assertFalse($this->instance->file_exists('folder')); } + + public function hashProvider() { + return array( + array('Foobar', 'md5'), + array('Foobar', 'sha1'), + array('Foobar', 'sha256'), + ); + } + + /** + * @dataProvider hashProvider + */ + public function testHash($data, $type) { + $this->instance->file_put_contents('hash.txt', $data); + $this->assertEquals(hash($type, $data), $this->instance->hash($type, 'hash.txt')); + $this->assertEquals(hash($type, $data, true), $this->instance->hash($type, 'hash.txt', true)); + } + + public function testHashInFileName() { + $this->instance->file_put_contents('#test.txt', 'data'); + $this->assertEquals('data', $this->instance->file_get_contents('#test.txt')); + + $this->instance->mkdir('#foo'); + $this->instance->file_put_contents('#foo/test.txt', 'data'); + $this->assertEquals('data', $this->instance->file_get_contents('#foo/test.txt')); + + $dh = $this->instance->opendir('#foo'); + $content = array(); + while ($file = readdir($dh)) { + if ($file != '.' and $file != '..') { + $content[] = $file; + } + } + + $this->assertEquals(array('test.txt'), $content); + } } diff --git a/tests/lib/group/group.php b/tests/lib/group/group.php index 3982c00e45f48be70f767d0a2c3d5302a19261cc..147532f99479df89b450011bb6669b4ffe2248fd 100644 --- a/tests/lib/group/group.php +++ b/tests/lib/group/group.php @@ -299,6 +299,68 @@ class Group extends \PHPUnit_Framework_TestCase { $this->assertEquals('user1', $user1->getUID()); } + public function testCountUsers() { + $backend1 = $this->getMock('OC_Group_Database'); + $userManager = $this->getUserManager(); + $group = new \OC\Group\Group('group1', array($backend1), $userManager); + + $backend1->expects($this->once()) + ->method('countUsersInGroup') + ->with('group1', '2') + ->will($this->returnValue(3)); + + $backend1->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $users = $group->count('2'); + + $this->assertSame(3, $users); + } + + public function testCountUsersMultipleBackends() { + $backend1 = $this->getMock('OC_Group_Database'); + $backend2 = $this->getMock('OC_Group_Database'); + $userManager = $this->getUserManager(); + $group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager); + + $backend1->expects($this->once()) + ->method('countUsersInGroup') + ->with('group1', '2') + ->will($this->returnValue(3)); + $backend1->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $backend2->expects($this->once()) + ->method('countUsersInGroup') + ->with('group1', '2') + ->will($this->returnValue(4)); + $backend2->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + $users = $group->count('2'); + + $this->assertSame(7, $users); + } + + public function testCountUsersNoMethod() { + $backend1 = $this->getMock('OC_Group_Database'); + $userManager = $this->getUserManager(); + $group = new \OC\Group\Group('group1', array($backend1), $userManager); + + $backend1->expects($this->never()) + ->method('countUsersInGroup'); + $backend1->expects($this->any()) + ->method('implementsActions') + ->will($this->returnValue(false)); + + $users = $group->count('2'); + + $this->assertSame(false, $users); + } + public function testDelete() { $backend = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); diff --git a/tests/lib/mail.php b/tests/lib/mail.php index a88a9d797ae7c405cbcc9a2a5195900a817c75e7..3cc9868e25e876fb48be8cd7afc0123f5ab730a1 100644 --- a/tests/lib/mail.php +++ b/tests/lib/mail.php @@ -8,6 +8,15 @@ class Test_Mail extends PHPUnit_Framework_TestCase { + protected function setUp() + { + if (!function_exists('idn_to_ascii')) { + $this->markTestSkipped( + 'The intl extension is not available.' + ); + } + } + /** * @dataProvider buildAsciiEmailProvider * @param $expected diff --git a/tests/lib/preview.php b/tests/lib/preview.php index 353b66fd6d66d9e8852aca36470fe84ba4e8cb84..4ef61fb82570cdfa39ed66e7a05a127f15549787 100644 --- a/tests/lib/preview.php +++ b/tests/lib/preview.php @@ -10,66 +10,73 @@ namespace Test; class Preview extends \PHPUnit_Framework_TestCase { - public function testIsPreviewDeleted() { - $user = $this->initFS(); + /** + * @var string + */ + private $user; + + /** + * @var \OC\Files\View + */ + private $rootView; + + public function setUp() { + $this->user = $this->initFS(); - $rootView = new \OC\Files\View(''); - $rootView->mkdir('/'.$user); - $rootView->mkdir('/'.$user.'/files'); + $this->rootView = new \OC\Files\View(''); + $this->rootView->mkdir('/'.$this->user); + $this->rootView->mkdir('/'.$this->user.'/files'); + } + + public function testIsPreviewDeleted() { - $samplefile = '/'.$user.'/files/test.txt'; + $sampleFile = '/'.$this->user.'/files/test.txt'; - $rootView->file_put_contents($samplefile, 'dummy file data'); + $this->rootView->file_put_contents($sampleFile, 'dummy file data'); $x = 50; $y = 50; - $preview = new \OC\Preview($user, 'files/', 'test.txt', $x, $y); + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', $x, $y); $preview->getPreview(); - $fileinfo = $rootView->getFileInfo($samplefile); - $fileid = $fileinfo['fileid']; + $fileInfo = $this->rootView->getFileInfo($sampleFile); + $fileId = $fileInfo['fileid']; - $thumbcachefile = '/' . $user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileid . '/' . $x . '-' . $y . '.png'; + $thumbCacheFile = '/' . $this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/' . $x . '-' . $y . '.png'; - $this->assertEquals($rootView->file_exists($thumbcachefile), true); + $this->assertEquals($this->rootView->file_exists($thumbCacheFile), true); $preview->deletePreview(); - $this->assertEquals($rootView->file_exists($thumbcachefile), false); + $this->assertEquals($this->rootView->file_exists($thumbCacheFile), false); } public function testAreAllPreviewsDeleted() { - $user = $this->initFS(); - $rootView = new \OC\Files\View(''); - $rootView->mkdir('/'.$user); - $rootView->mkdir('/'.$user.'/files'); + $sampleFile = '/'.$this->user.'/files/test.txt'; - $samplefile = '/'.$user.'/files/test.txt'; - - $rootView->file_put_contents($samplefile, 'dummy file data'); + $this->rootView->file_put_contents($sampleFile, 'dummy file data'); $x = 50; $y = 50; - $preview = new \OC\Preview($user, 'files/', 'test.txt', $x, $y); + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', $x, $y); $preview->getPreview(); - $fileinfo = $rootView->getFileInfo($samplefile); - $fileid = $fileinfo['fileid']; + $fileInfo = $this->rootView->getFileInfo($sampleFile); + $fileId = $fileInfo['fileid']; - $thumbcachefolder = '/' . $user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileid . '/'; + $thumbCacheFolder = '/' . $this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/'; - $this->assertEquals($rootView->is_dir($thumbcachefolder), true); + $this->assertEquals($this->rootView->is_dir($thumbCacheFolder), true); $preview->deleteAllPreviews(); - $this->assertEquals($rootView->is_dir($thumbcachefolder), false); + $this->assertEquals($this->rootView->is_dir($thumbCacheFolder), false); } public function testIsMaxSizeWorking() { - $user = $this->initFS(); $maxX = 250; $maxY = 250; @@ -77,15 +84,11 @@ class Preview extends \PHPUnit_Framework_TestCase { \OC_Config::setValue('preview_max_x', $maxX); \OC_Config::setValue('preview_max_y', $maxY); - $rootView = new \OC\Files\View(''); - $rootView->mkdir('/'.$user); - $rootView->mkdir('/'.$user.'/files'); - - $samplefile = '/'.$user.'/files/test.txt'; + $sampleFile = '/'.$this->user.'/files/test.txt'; - $rootView->file_put_contents($samplefile, 'dummy file data'); + $this->rootView->file_put_contents($sampleFile, 'dummy file data'); - $preview = new \OC\Preview($user, 'files/', 'test.txt', 1000, 1000); + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', 1000, 1000); $image = $preview->getPreview(); $this->assertEquals($image->width(), $maxX); @@ -108,18 +111,13 @@ class Preview extends \PHPUnit_Framework_TestCase { * @dataProvider txtBlacklist */ public function testIsTransparent($extension, $data, $expectedResult) { - $user = $this->initFS(); - - $rootView = new \OC\Files\View(''); - $rootView->mkdir('/'.$user); - $rootView->mkdir('/'.$user.'/files'); $x = 32; $y = 32; - $sample = '/'.$user.'/files/test.'.$extension; - $rootView->file_put_contents($sample, $data); - $preview = new \OC\Preview($user, 'files/', 'test.'.$extension, $x, $y); + $sample = '/'.$this->user.'/files/test.'.$extension; + $this->rootView->file_put_contents($sample, $data); + $preview = new \OC\Preview($this->user, 'files/', 'test.'.$extension, $x, $y); $image = $preview->getPreview(); $resource = $image->resource(); @@ -133,6 +131,64 @@ class Preview extends \PHPUnit_Framework_TestCase { ); } + public function testCreationFromCached() { + + $sampleFile = '/'.$this->user.'/files/test.txt'; + + $this->rootView->file_put_contents($sampleFile, 'dummy file data'); + + // create base preview + $x = 150; + $y = 150; + + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', $x, $y); + $preview->getPreview(); + + $fileInfo = $this->rootView->getFileInfo($sampleFile); + $fileId = $fileInfo['fileid']; + + $thumbCacheFile = '/' . $this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/' . $x . '-' . $y . '.png'; + + $this->assertEquals($this->rootView->file_exists($thumbCacheFile), true); + + + // create smaller previews + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', 50, 50); + $isCached = $preview->isCached($fileId); + + $this->assertEquals($this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/150-150.png', $isCached); + } + + /* + public function testScalingUp() { + + $sampleFile = '/'.$this->user.'/files/test.txt'; + + $this->rootView->file_put_contents($sampleFile, 'dummy file data'); + + // create base preview + $x = 150; + $y = 150; + + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', $x, $y); + $preview->getPreview(); + + $fileInfo = $this->rootView->getFileInfo($sampleFile); + $fileId = $fileInfo['fileid']; + + $thumbCacheFile = '/' . $this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/' . $x . '-' . $y . '.png'; + + $this->assertEquals($this->rootView->file_exists($thumbCacheFile), true); + + + // create bigger previews - with scale up + $preview = new \OC\Preview($this->user, 'files/', 'test.txt', 250, 250); + $isCached = $preview->isCached($fileId); + + $this->assertEquals($this->user . '/' . \OC\Preview::THUMBNAILS_FOLDER . '/' . $fileId . '/150-150.png', $isCached); + } + */ + private function initFS() { // create a new user with his own filesystem view // this gets called by each test in this test class diff --git a/tests/lib/public/ocpconfig.php b/tests/lib/public/ocpconfig.php new file mode 100644 index 0000000000000000000000000000000000000000..43a9ca625eecc149349edba5a6a974c2a661ad58 --- /dev/null +++ b/tests/lib/public/ocpconfig.php @@ -0,0 +1,37 @@ +. + */ + +class Test_OCPConfig extends PHPUnit_Framework_TestCase +{ + + public function testSetAppValueIfSetToNull() { + + $key = uniqid("key-"); + + $result = \OCP\Config::setAppValue('unit-test', $key, null); + $this->assertTrue($result); + + $result = \OCP\Config::setAppValue('unit-test', $key, '12'); + $this->assertTrue($result); + + } + +} diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php index b5cba9430aac998bb547f03de03525fcc4847a1a..aae91fa1087e6c576bae24ea9e4b748dd4938658 100644 --- a/tests/lib/share/share.php +++ b/tests/lib/share/share.php @@ -282,7 +282,7 @@ class Test_Share extends PHPUnit_Framework_TestCase { OC_User::setUserId($this->user2); $this->assertEquals(array(OCP\PERMISSION_READ), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_PERMISSIONS)); OC_User::setUserId($this->user3); - $this->assertFalse(OCP\Share::getItemSharedWith('test', 'test.txt')); + $this->assertSame(array(), OCP\Share::getItemSharedWith('test', 'test.txt')); // Reshare again, and then have owner unshare OC_User::setUserId($this->user1); @@ -292,9 +292,9 @@ class Test_Share extends PHPUnit_Framework_TestCase { OC_User::setUserId($this->user1); $this->assertTrue(OCP\Share::unshare('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $this->user2)); OC_User::setUserId($this->user2); - $this->assertFalse(OCP\Share::getItemSharedWith('test', 'test.txt')); + $this->assertSame(array(), OCP\Share::getItemSharedWith('test', 'test.txt')); OC_User::setUserId($this->user3); - $this->assertFalse(OCP\Share::getItemSharedWith('test', 'test.txt')); + $this->assertSame(array(), OCP\Share::getItemSharedWith('test', 'test.txt')); // Attempt target conflict OC_User::setUserId($this->user1); @@ -325,7 +325,7 @@ class Test_Share extends PHPUnit_Framework_TestCase { ); OC_User::setUserId($this->user2); - $this->assertFalse( + $this->assertSame(array(), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE), 'Failed asserting that user 2 no longer has access to test.txt after expiration.' ); @@ -526,13 +526,13 @@ class Test_Share extends PHPUnit_Framework_TestCase { ); OC_User::setUserId($this->user2); - $this->assertFalse( + $this->assertSame(array(), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE), 'Failed asserting that user 2 no longer has access to test.txt after expiration.' ); OC_User::setUserId($this->user3); - $this->assertFalse( + $this->assertSame(array(), OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE), 'Failed asserting that user 3 no longer has access to test.txt after expiration.' ); diff --git a/tests/lib/urlgenerator.php b/tests/lib/urlgenerator.php index 875a7f06580bb87ebe5292f3e781ed7b4a0f0f6f..8e605d88f32f26b13f275ca1dbe39d95e709a23c 100644 --- a/tests/lib/urlgenerator.php +++ b/tests/lib/urlgenerator.php @@ -12,17 +12,32 @@ class Test_Urlgenerator extends PHPUnit_Framework_TestCase { /** * @small * @brief test absolute URL construction - * @dataProvider provideURLs + * @dataProvider provideDocRootURLs */ - function testGetAbsoluteURL($url, $expectedResult) { + function testGetAbsoluteURLDocRoot($url, $expectedResult) { + \OC::$WEBROOT = ''; $urlGenerator = new \OC\URLGenerator(null); $result = $urlGenerator->getAbsoluteURL($url); $this->assertEquals($expectedResult, $result); } - public function provideURLs() { + /** + * @small + * @brief test absolute URL construction + * @dataProvider provideSubDirURLs + */ + function testGetAbsoluteURLSubDir($url, $expectedResult) { + + \OC::$WEBROOT = '/owncloud'; + $urlGenerator = new \OC\URLGenerator(null); + $result = $urlGenerator->getAbsoluteURL($url); + + $this->assertEquals($expectedResult, $result); + } + + public function provideDocRootURLs() { return array( array("index.php", "http://localhost/index.php"), array("/index.php", "http://localhost/index.php"), @@ -30,5 +45,14 @@ class Test_Urlgenerator extends PHPUnit_Framework_TestCase { array("apps/index.php", "http://localhost/apps/index.php"), ); } + + public function provideSubDirURLs() { + return array( + array("index.php", "http://localhost/owncloud/index.php"), + array("/index.php", "http://localhost/owncloud/index.php"), + array("/apps/index.php", "http://localhost/owncloud/apps/index.php"), + array("apps/index.php", "http://localhost/owncloud/apps/index.php"), + ); + } }