diff --git a/.gitignore b/.gitignore index e61ec6f035..b24edc9128 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 b9c1a3702c..bc2beee81a 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/.htaccess b/.htaccess old mode 100755 new mode 100644 index 4ba5095e14..714e8af213 --- a/.htaccess +++ b/.htaccess @@ -6,8 +6,6 @@ RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION -ErrorDocument 403 /core/templates/403.php -ErrorDocument 404 /core/templates/404.php php_value upload_max_filesize 513M php_value post_max_size 513M @@ -20,12 +18,12 @@ php_value mbstring.func_overload 0 RewriteEngine on RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}] -RewriteRule ^.well-known/host-meta /public.php?service=host-meta [QSA,L] -RewriteRule ^.well-known/host-meta.json /public.php?service=host-meta-json [QSA,L] -RewriteRule ^.well-known/carddav /remote.php/carddav/ [R] -RewriteRule ^.well-known/caldav /remote.php/caldav/ [R] -RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L] -RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L] +RewriteRule ^\.well-known/host-meta /public.php?service=host-meta [QSA,L] +RewriteRule ^\.well-known/host-meta\.json /public.php?service=host-meta-json [QSA,L] +RewriteRule ^\.well-known/carddav /remote.php/carddav/ [R] +RewriteRule ^\.well-known/caldav /remote.php/caldav/ [R] +RewriteRule ^apps/calendar/caldav\.php remote.php/caldav/ [QSA,L] +RewriteRule ^apps/contacts/carddav\.php remote.php/carddav/ [QSA,L] RewriteRule ^apps/([^/]*)/(.*\.(php))$ index.php?app=$1&getfile=$2 [QSA,L] RewriteRule ^remote/(.*) remote.php [QSA,L] diff --git a/.jshintrc b/.jshintrc index f40dd22b5f..77f9e9f143 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,5 +1,5 @@ { - "camelCase": true, + "camelcase": true, "eqeqeq": true, "immed": true, "latedef": false, @@ -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 new file mode 100644 index 0000000000..d1dbb20139 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,28 @@ +filter: + excluded_paths: + - '3rdparty/*' + - 'apps/*/3rdparty/*' + - 'l10n/*' + - 'core/l10n/*' + - 'apps/*/l10n/*' + - 'lib/l10n/*' + - 'core/js/tests/lib/*.js' + - 'core/js/tests/specs/*.js' + - 'core/js/jquery-1.10.0.js' + - 'core/js/jquery-1.10.0.min.js' + - 'core/js/jquery-migrate-1.2.1.js' + - 'core/js/jquery-migrate-1.2.1.min.js' + - 'core/js/jquery-showpassword.js' + - 'core/js/jquery-tipsy.js' + - 'core/js/jquery.infieldlabel.js' + - '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: + - javascript + - php + diff --git a/3rdparty b/3rdparty index 478de4b756..ef80977061 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 478de4b756f3729f762d838b29f69f2a40e5f4f8 +Subproject commit ef80977061d4bc3a2d8ee0bf23a8287a3222b628 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 70bd85fabf..ff3b270320 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,7 +32,7 @@ If you have questions about how to install or use ownCloud, please direct these Help us to maximize the effort we can spend fixing issues and adding new features, by not reporting duplicate issues. [template]: https://raw.github.com/owncloud/core/master/issue_template.md -[mailinglist]: https://mail.kde.org/mailman/listinfo/owncloud +[mailinglist]: http://mailman.owncloud.org/mailman/listinfo/owncloud [forum]: http://forum.owncloud.org/ [irc]: http://webchat.freenode.net/?channels=owncloud&uio=d4 diff --git a/README.md b/README.md index 3f76c1a477..0b13f11e76 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/delete.php b/apps/files/ajax/delete.php index 69f859daa9..f6aa4f0c90 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -1,15 +1,14 @@ close(); + // Get data $dir = stripslashes($_POST["dir"]); $files = isset($_POST["file"]) ? $_POST["file"] : $_POST["files"]; -$allFiles = isset($_POST["allfiles"]) ? $_POST["allfiles"] : $_POST["allfiles"]; +$allFiles = isset($_POST["allfiles"]) ? $_POST["allfiles"] : false; if ($allFiles === 'true') { $allFiles = true; } diff --git a/apps/files/ajax/download.php b/apps/files/ajax/download.php index 6a34cbe4ef..4b4a7f8948 100644 --- a/apps/files/ajax/download.php +++ b/apps/files/ajax/download.php @@ -21,14 +21,9 @@ * */ -// only need filesystem apps -$RUNTIME_APPTYPES=array('filesystem'); - -// Init owncloud - - // Check if we are a user OCP\User::checkLoggedIn(); +\OC::$session->close(); $files = $_GET["files"]; $dir = $_GET["dir"]; diff --git a/apps/files/ajax/getstoragestats.php b/apps/files/ajax/getstoragestats.php index dd7c7dc557..dd8af39bad 100644 --- a/apps/files/ajax/getstoragestats.php +++ b/apps/files/ajax/getstoragestats.php @@ -1,8 +1,5 @@ close(); // send back json OCP\JSON::success(array('data' => \OCA\Files\Helper::buildFileStorageStatistics($dir))); diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index c8286bc15c..2d76b68501 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -1,48 +1,27 @@ close(); // Load the files $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/mimeicon.php b/apps/files/ajax/mimeicon.php index dbb8b60112..6557ff941a 100644 --- a/apps/files/ajax/mimeicon.php +++ b/apps/files/ajax/mimeicon.php @@ -1,3 +1,4 @@ close(); print OC_Helper::mimetypeIcon($_GET['mime']); diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 93063e52eb..0a8dbc24a6 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -1,10 +1,8 @@ close(); // Get data $dir = stripslashes($_POST["dir"]); @@ -18,7 +16,7 @@ if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) { exit; } -if ($dir != '' || $file != 'Shared') { +if ($target != '' || strtolower($file) != 'shared') { $targetFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 0187b20075..7d6be59bea 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -7,7 +7,8 @@ if(!OC_User::isLoggedIn()) { exit; } -session_write_close(); +\OC::$session->close(); + // Get the params $dir = isset( $_REQUEST['dir'] ) ? '/'.trim($_REQUEST['dir'], '/\\') : ''; $filename = isset( $_REQUEST['filename'] ) ? trim($_REQUEST['filename'], '/\\') : ''; @@ -111,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)))); } @@ -138,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 b2b4fb27f7..89c241189d 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -5,6 +5,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); +\OC::$session->close(); // Get the params $dir = isset( $_POST['dir'] ) ? stripslashes($_POST['dir']) : ''; @@ -57,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 40da32b223..0000000000 --- a/apps/files/ajax/rawlist.php +++ /dev/null @@ -1,60 +0,0 @@ -getPreviewManager()->isMimeSupported($file['mimetype']); - $file["date"] = OCP\Util::formatDate($file["mtime"]); - $file['mimetype_icon'] = \OCA\Files\Helper::determineIcon($file); - $files[] = $file; - } -} - -if (is_array($mimetypes) && count($mimetypes)) { - foreach ($mimetypes as $mimetype) { - foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, $mimetype ) as $file ) { - $file['directory'] = $dir; - $file['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($file['mimetype']); - $file["date"] = OCP\Util::formatDate($file["mtime"]); - $file['mimetype_icon'] = \OCA\Files\Helper::determineIcon($file); - $files[] = $file; - } - } -} else { - foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $file ) { - $file['directory'] = $dir; - $file['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($file['mimetype']); - $file["date"] = OCP\Util::formatDate($file["mtime"]); - $file['mimetype_icon'] = \OCA\Files\Helper::determineIcon($file); - $files[] = $file; - } -} - -// Sort by name -usort($files, function ($a, $b) { - if ($a['name'] === $b['name']) { - return 0; - } - return ($a['name'] < $b['name']) ? -1 : 1; -}); - -OC_JSON::success(array('data' => $files)); diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php index 5b07c306af..fa3ddace63 100644 --- a/apps/files/ajax/rename.php +++ b/apps/files/ajax/rename.php @@ -23,6 +23,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); +\OC::$session->close(); $files = new \OCA\Files\App( \OC\Files\Filesystem::getView(), diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 5b32b6db9b..d5d8848380 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -1,6 +1,6 @@ close(); $force = (isset($_GET['force']) and ($_GET['force'] === 'true')); $dir = isset($_GET['dir']) ? $_GET['dir'] : ''; diff --git a/apps/files/ajax/upgrade.php b/apps/files/ajax/upgrade.php deleted file mode 100644 index 7237b02c0b..0000000000 --- a/apps/files/ajax/upgrade.php +++ /dev/null @@ -1,44 +0,0 @@ -hasItems()) { - OC_Hook::connect('\OC\Files\Cache\Upgrade', 'migrate_path', $listener, 'upgradePath'); - - OC_DB::beginTransaction(); - $upgrade = new \OC\Files\Cache\Upgrade($legacy); - $count = $legacy->getCount(); - $eventSource->send('total', $count); - $upgrade->upgradePath('/' . $user . '/files'); - OC_DB::commit(); -} -\OC\Files\Cache\Upgrade::upgradeDone($user); -$eventSource->send('done', true); -$eventSource->close(); - -class UpgradeListener { - /** - * @var OC_EventSource $eventSource - */ - private $eventSource; - - private $count = 0; - private $lastSend = 0; - - public function __construct($eventSource) { - $this->eventSource = $eventSource; - } - - public function upgradePath($path) { - $this->count++; - if ($this->count > ($this->lastSend + 5)) { - $this->lastSend = $this->count; - $this->eventSource->send('count', $this->count); - } - } -} diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 145f40c50d..a5ce7b257d 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'] : '/'; @@ -58,6 +62,10 @@ if (empty($_POST['dirToken'])) { OCP\JSON::callCheck(); +if (!\OCP\App::isEnabled('files_encryption')) { + // encryption app need to create keys later, so can't close too early + \OC::$session->close(); +} // get array with current storage stats (e.g. max file size) @@ -103,22 +111,32 @@ if ($maxUploadFileSize >= 0 and $totalSize > $maxUploadFileSize) { } $result = array(); +$directory = ''; if (strpos($dir, '..') === false) { $fileCount = count($files['name']); for ($i = 0; $i < $fileCount; $i++) { + + // Get the files directory + if(isset($_POST['file_directory']) === true) { + $directory = '/'.$_POST['file_directory']; + } + // $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder if (isset($_POST['resolution']) && $_POST['resolution']==='autorename') { // append a number in brackets like 'filename (2).ext' - $target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]); + $target = OCP\Files::buildNotExistingFileName(stripslashes($dir.$directory), $files['name'][$i]); } else { - $target = \OC\Files\Filesystem::normalizePath(stripslashes($dir).'/'.$files['name'][$i]); + $target = \OC\Files\Filesystem::normalizePath(stripslashes($dir.$directory).'/'.$files['name'][$i]); } - - $directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir)); - if (isset($public_directory)) { - // If we are uploading from the public app, - // we want to send the relative path in the ajax request. - $directory = $public_directory; + + if(empty($directory) === true) + { + $directory = \OC\Files\Filesystem::normalizePath(stripslashes($dir)); + if (isset($public_directory)) { + // If we are uploading from the public app, + // we want to send the relative path in the ajax request. + $directory = $public_directory; + } } if ( ! \OC\Files\Filesystem::file_exists($target) @@ -137,19 +155,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 { @@ -165,19 +178,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; } } } @@ -187,7 +196,6 @@ if (strpos($dir, '..') === false) { if ($error === false) { OCP\JSON::encodedPrint($result); - exit(); } else { OCP\JSON::error(array(array('data' => array_merge(array('message' => $error, 'code' => $errorCode), $storageStats)))); } diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index 909baca92e..15a2913378 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -12,13 +12,6 @@ OCP\App::addNavigationEntry(array("id" => "files_index", OC_Search::registerProvider('OC_Search_Provider_File'); -// cache hooks must be connected before all other apps. -// since 'files' is always loaded first the hooks need to be connected here -\OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Updater', 'writeHook'); -\OC_Hook::connect('OC_Filesystem', 'post_touch', '\OC\Files\Cache\Updater', 'touchHook'); -\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Updater', 'deleteHook'); -\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook'); - \OCP\BackgroundJob::addRegularTask('\OC\Files\Cache\BackgroundWatcher', 'checkNext'); $templateManager = OC_Helper::getFileTemplateManager(); diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php index ef22fe9218..c1baee4f1e 100644 --- a/apps/files/appinfo/remote.php +++ b/apps/files/appinfo/remote.php @@ -22,23 +22,14 @@ * 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(); $lockBackend = new OC_Connector_Sabre_Locks(); $requestBackend = new OC_Connector_Sabre_Request(); -// Create ownCloud Dir -$rootDir = new OC_Connector_Sabre_Directory(''); -$objectTree = new \OC\Connector\Sabre\ObjectTree($rootDir); - // Fire up server +$objectTree = new \OC\Connector\Sabre\ObjectTree(); $server = new OC_Connector_Sabre_Server($objectTree); $server->httpRequest = $requestBackend; $server->setBaseUri($baseuri); @@ -47,12 +38,23 @@ $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)); // Show something in the Browser, but no upload +$server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); $server->addPlugin(new OC_Connector_Sabre_FilesPlugin()); -$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin()); -$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin()); $server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin()); $server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav')); +// wait with registering these until auth is handled and the filesystem is setup +$server->subscribeEvent('beforeMethod', function () use ($server, $objectTree) { + $view = \OC\Files\Filesystem::getView(); + $rootInfo = $view->getFileInfo(''); + + // Create ownCloud Dir + $rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo); + $objectTree->init($rootDir, $view); + + $server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view)); + $server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view)); +}, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request + // And off we go! $server->exec(); diff --git a/apps/files/command/scan.php b/apps/files/command/scan.php index f334f29a93..25ab70af36 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 af863aca33..533050691d 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -51,7 +51,7 @@ margin: 5px; padding-left: 42px; padding-bottom: 2px; - background-position: initial; + background-position: left center; cursor: pointer; } #new > ul > li > p { @@ -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; } @@ -310,7 +310,6 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; } /* Actions for selected files */ .selectedActions { - display: none; position: absolute; top: -1px; right: 0; diff --git a/apps/files/css/mobile.css b/apps/files/css/mobile.css new file mode 100644 index 0000000000..3ad7d63483 --- /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 ad7a2e210e..a4e9a93850 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -27,19 +27,22 @@ 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', 'filesummary'); +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,100 +62,53 @@ if ($isIE8 && isset($_GET['dir'])){ exit(); } -$ajaxLoad = false; -$files = array(); $user = OC_User::getUser(); -if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache - $needUpgrade = true; -} else { - 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); - } - $needUpgrade = false; -} $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(); -if ($needUpgrade) { - OCP\Util::addscript('files', 'upgrade'); - $tmpl = new OCP\Template('files', 'upgrade', 'user'); - $tmpl->printPage(); -} else { - // information about storage capacities - $storageInfo=OC_Helper::getStorageInfo($dir); - $freeSpace=$storageInfo['free']; - $uploadLimit=OCP\Util::uploadLimit(); - $maxUploadFilesize=OCP\Util::maxUploadFilesize($dir); - $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; - if (OC_App::isEnabled('files_encryption')) { - $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); - $encryptionInitStatus = $session->getInitialized(); - } - - $trashEnabled = \OCP\App::isEnabled('files_trashbin'); - $trashEmpty = true; - 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 - $tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); - $tmpl->assign('freeSpace', $freeSpace); - $tmpl->assign('uploadLimit', $uploadLimit); // PHP upload limit - $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); - $tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']); - $tmpl->assign('isPublic', false); - $tmpl->assign('publicUploadEnabled', $publicUploadEnabled); - $tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); - $tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_mail_notification', 'yes')); - $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(); +// information about storage capacities +$storageInfo=OC_Helper::getStorageInfo($dir, $dirInfo); +$freeSpace=$storageInfo['free']; +$uploadLimit=OCP\Util::uploadLimit(); +$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; +if (OC_App::isEnabled('files_encryption')) { + $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); + $encryptionInitStatus = $session->getInitialized(); } + +$trashEnabled = \OCP\App::isEnabled('files_trashbin'); +$trashEmpty = true; +if ($trashEnabled) { + $trashEmpty = \OCA\Files_Trashbin\Trashbin::isEmpty($user); +} + +OCP\Util::addscript('files', 'fileactions'); +OCP\Util::addscript('files', 'files'); +OCP\Util::addscript('files', 'keyboardshortcuts'); +$tmpl = new OCP\Template('files', 'index', 'user'); +$tmpl->assign('dir', $dir); +$tmpl->assign('permissions', $permissions); +$tmpl->assign('trash', $trashEnabled); +$tmpl->assign('trashEmpty', $trashEmpty); +$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); // minimium of freeSpace and uploadLimit +$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); +$tmpl->assign('freeSpace', $freeSpace); +$tmpl->assign('uploadLimit', $uploadLimit); // PHP upload limit +$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); +$tmpl->assign('usedSpacePercent', (int)$storageInfo['relative']); +$tmpl->assign('isPublic', false); +$tmpl->assign('publicUploadEnabled', $publicUploadEnabled); +$tmpl->assign("encryptedFiles", \OCP\Util::encryptedFiles()); +$tmpl->assign("mailNotificationEnabled", $config->getAppValue('core', 'shareapi_allow_mail_notification', 'yes')); +$tmpl->assign("allowShareWithLink", $config->getAppValue('core', 'shareapi_allow_links', 'yes')); +$tmpl->assign("encryptionInitStatus", $encryptionInitStatus); +$tmpl->assign('disableSharing', false); + +$tmpl->printPage(); diff --git a/apps/files/js/admin.js b/apps/files/js/admin.js index f735079fcb..842b73c0ca 100644 --- a/apps/files/js/admin.js +++ b/apps/files/js/admin.js @@ -8,19 +8,22 @@ * */ -function switchPublicFolder() -{ +function switchPublicFolder() { var publicEnable = $('#publicEnable').is(':checked'); - var sharingaimGroup = $('input:radio[name=sharingaim]'); //find all radiobuttons of that group + // find all radiobuttons of that group + var sharingaimGroup = $('input:radio[name=sharingaim]'); $.each(sharingaimGroup, function(index, sharingaimItem) { - sharingaimItem.disabled = !publicEnable; //set all buttons to the correct state + // set all buttons to the correct state + sharingaimItem.disabled = !publicEnable; }); } -$(document).ready(function(){ - switchPublicFolder(); // Execute the function after loading DOM tree - $('#publicEnable').click(function(){ - switchPublicFolder(); // To get rid of onClick() +$(document).ready(function() { + // Execute the function after loading DOM tree + switchPublicFolder(); + $('#publicEnable').click(function() { + // To get rid of onClick() + switchPublicFolder(); }); $('#allowZipDownload').bind('change', function() { diff --git a/apps/files/js/breadcrumb.js b/apps/files/js/breadcrumb.js new file mode 100644 index 0000000000..5bc2fac136 --- /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 f962a7044a..963fc64782 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -82,7 +82,7 @@ OC.Upload = { */ isProcessing:function() { var count = 0; - + jQuery.each(this._uploads,function(i, data) { if (data.state() === 'pending') { count++; @@ -177,549 +177,521 @@ OC.Upload = { checkExistingFiles: function (selection, callbacks) { // TODO check filelist before uploading and show dialog on conflicts, use callbacks callbacks.onNoConflicts(selection); + }, + + init: function() { + if ( $('#file_upload_start').exists() ) { + + var file_upload_param = { + dropZone: $('#content'), // restrict dropZone to content div + autoUpload: false, + sequentialUploads: true, + //singleFileUploads is on by default, so the data.files array will always have length 1 + /** + * on first add of every selection + * - check all files of originalFiles array with files in dir + * - on conflict show dialog + * - skip all -> remember as single skip action for all conflicting files + * - replace all -> remember as single replace action for all conflicting files + * - choose -> show choose dialog + * - mark files to keep + * - when only existing -> remember as single skip action + * - when only new -> remember as single replace action + * - when both -> remember as single autorename action + * - start uploading selection + * @param {object} e + * @param {object} data + * @returns {boolean} + */ + add: function(e, data) { + OC.Upload.log('add', e, data); + var that = $(this); + var freeSpace; + + // we need to collect all data upload objects before starting the upload so we can check their existence + // and set individual conflict actions. unfortunately there is only one variable that we can use to identify + // the selection a data upload is part of, so we have to collect them in data.originalFiles + // turning singleFileUploads off is not an option because we want to gracefully handle server errors like + // already exists + + // create a container where we can store the data objects + if ( ! data.originalFiles.selection ) { + // initialize selection and remember number of files to upload + data.originalFiles.selection = { + uploads: [], + filesToUpload: data.originalFiles.length, + totalBytes: 0 + }; + } + var selection = data.originalFiles.selection; + + // add uploads + if ( selection.uploads.length < selection.filesToUpload ) { + // remember upload + selection.uploads.push(data); + } + + //examine file + var file = data.files[0]; + try { + // FIXME: not so elegant... need to refactor that method to return a value + Files.isFileNameValid(file.name); + } + catch (errorMessage) { + data.textStatus = 'invalidcharacters'; + data.errorThrown = errorMessage; + } + + // in case folder drag and drop is not supported file will point to a directory + // http://stackoverflow.com/a/20448357 + if (!file.type && file.size%4096 === 0 && file.size <= 102400) { + try { + reader = new FileReader(); + reader.readAsBinaryString(f); + } catch (NS_ERROR_FILE_ACCESS_DENIED) { + //file is a directory + data.textStatus = 'dirorzero'; + data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', + {filename: file.name} + ); + } + } + + // add size + selection.totalBytes += file.size; + + // check PHP upload limit + if (selection.totalBytes > $('#upload_limit').val()) { + data.textStatus = 'sizeexceedlimit'; + data.errorThrown = t('files', 'Total file size {size1} exceeds upload limit {size2}', { + 'size1': humanFileSize(selection.totalBytes), + 'size2': humanFileSize($('#upload_limit').val()) + }); + } + + // check free space + freeSpace = $('#free_space').val(); + if (freeSpace >= 0 && selection.totalBytes > freeSpace) { + data.textStatus = 'notenoughspace'; + data.errorThrown = t('files', 'Not enough free space, you are uploading {size1} but only {size2} is left', { + 'size1': humanFileSize(selection.totalBytes), + 'size2': humanFileSize($('#free_space').val()) + }); + } + + // end upload for whole selection on error + if (data.errorThrown) { + // trigger fileupload fail + var fu = that.data('blueimp-fileupload') || that.data('fileupload'); + fu._trigger('fail', e, data); + return false; //don't upload anything + } + + // check existing files when all is collected + if ( selection.uploads.length >= selection.filesToUpload ) { + + //remove our selection hack: + delete data.originalFiles.selection; + + var callbacks = { + + onNoConflicts: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.submit(); + }); + }, + onSkipConflicts: function (selection) { + //TODO mark conflicting files as toskip + }, + onReplaceConflicts: function (selection) { + //TODO mark conflicting files as toreplace + }, + onChooseConflicts: function (selection) { + //TODO mark conflicting files as chosen + }, + onCancel: function (selection) { + $.each(selection.uploads, function(i, upload) { + upload.abort(); + }); + } + }; + + OC.Upload.checkExistingFiles(selection, callbacks); + + } + + return true; // continue adding files + }, + /** + * called after the first add, does NOT have the data param + * @param {object} e + */ + start: function(e) { + OC.Upload.log('start', e, null); + //hide the tooltip otherwise it covers the progress bar + $('#upload').tipsy('hide'); + }, + submit: function(e, data) { + OC.Upload.rememberUpload(data); + if ( ! data.formData ) { + var fileDirectory = ''; + if(typeof data.files[0].relativePath !== 'undefined') { + fileDirectory = data.files[0].relativePath; + } + // noone set update parameters, we set the minimum + data.formData = { + requesttoken: oc_requesttoken, + dir: $('#dir').val(), + file_directory: fileDirectory + }; + } + }, + fail: function(e, data) { + OC.Upload.log('fail', e, data); + if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { + if (data.textStatus === 'abort') { + OC.Notification.show(t('files', 'Upload cancelled.')); + } else { + // HTTP connection problem + OC.Notification.show(data.errorThrown); + if (data.result) { + var result = JSON.parse(data.result); + if (result && result[0] && result[0].data && result[0].data.code === 'targetnotfound') { + // abort upload of next files if any + OC.Upload.cancelUploads(); + } + } + } + //hide notification after 10 sec + setTimeout(function() { + OC.Notification.hide(); + }, 10000); + } + OC.Upload.deleteUpload(data); + }, + /** + * called for every successful upload + * @param {object} e + * @param {object} data + */ + done:function(e, data) { + OC.Upload.log('done', e, data); + // handle different responses (json or body from iframe for ie) + var response; + if (typeof data.result === 'string') { + response = data.result; + } else { + //fetch response from iframe + response = data.result[0].body.innerText; + } + var result=$.parseJSON(response); + + delete data.jqXHR; + + if (result.status === 'error' && result.data && result.data.message){ + data.textStatus = 'servererror'; + data.errorThrown = result.data.message; + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } else if (typeof result[0] === 'undefined') { + data.textStatus = 'servererror'; + data.errorThrown = t('files', 'Could not get result from server.'); + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } else if (result[0].status === 'existserror') { + //show "file already exists" dialog + var original = result[0]; + var replacement = data.files[0]; + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + OC.dialogs.fileexists(data, original, replacement, OC.Upload, fu); + } else if (result[0].status !== 'success') { + //delete data.jqXHR; + data.textStatus = 'servererror'; + data.errorThrown = result[0].data.message; // error message has been translated on server + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + fu._trigger('fail', e, data); + } + }, + /** + * called after last upload + * @param {object} e + * @param {object} data + */ + stop: function(e, data) { + OC.Upload.log('stop', e, data); + } + }; + + // initialize jquery fileupload (blueimp) + var fileupload = $('#file_upload_start').fileupload(file_upload_param); + window.file_upload_param = fileupload; + + if (supportAjaxUploadWithProgress()) { + + // add progress handlers + fileupload.on('fileuploadadd', function(e, data) { + OC.Upload.log('progress handle fileuploadadd', e, data); + //show cancel button + //if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie? + // $('#uploadprogresswrapper input.stop').show(); + //} + }); + // add progress handlers + fileupload.on('fileuploadstart', function(e, data) { + OC.Upload.log('progress handle fileuploadstart', e, data); + $('#uploadprogresswrapper input.stop').show(); + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + }); + fileupload.on('fileuploadprogress', function(e, data) { + OC.Upload.log('progress handle fileuploadprogress', e, data); + //TODO progressbar in row + }); + fileupload.on('fileuploadprogressall', function(e, data) { + OC.Upload.log('progress handle fileuploadprogressall', e, data); + var progress = (data.loaded / data.total) * 100; + $('#uploadprogressbar').progressbar('value', progress); + }); + fileupload.on('fileuploadstop', function(e, data) { + OC.Upload.log('progress handle fileuploadstop', e, data); + + $('#uploadprogresswrapper input.stop').fadeOut(); + $('#uploadprogressbar').fadeOut(); + Files.updateStorageStatistics(); + }); + fileupload.on('fileuploadfail', function(e, data) { + OC.Upload.log('progress handle fileuploadfail', e, data); + //if user pressed cancel hide upload progress bar and cancel button + if (data.errorThrown === 'abort') { + $('#uploadprogresswrapper input.stop').fadeOut(); + $('#uploadprogressbar').fadeOut(); + } + }); + + } else { + console.log('skipping file progress because your browser is broken'); + } + } + + $.assocArraySize = function(obj) { + // http://stackoverflow.com/a/6700/11236 + var size = 0, key; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + size++; + } + } + return size; + }; + + // warn user not to leave the page while upload is in progress + $(window).on('beforeunload', function(e) { + if (OC.Upload.isProcessing()) { + return t('files', 'File upload is in progress. Leaving the page now will cancel the upload.'); + } + }); + + //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) + if (navigator.userAgent.search(/konqueror/i) === -1) { + $('#file_upload_start').attr('multiple', 'multiple'); + } + + $(document).click(function(ev) { + // do not close when clicking in the dropdown + if ($(ev.target).closest('#new').length){ + return; + } + $('#new>ul').hide(); + $('#new').removeClass('active'); + if ($('#new .error').length > 0) { + $('#new .error').tipsy('hide'); + } + $('#new li').each(function(i,element) { + if ($(element).children('p').length === 0) { + $(element).children('form').remove(); + $(element).append('

'+$(element).data('text')+'

'); + } + }); + }); + $('#new').click(function(event) { + event.stopPropagation(); + }); + $('#new>a').click(function() { + $('#new>ul').toggle(); + $('#new').toggleClass('active'); + }); + $('#new li').click(function() { + if ($(this).children('p').length === 0) { + return; + } + + $('#new .error').tipsy('hide'); + + $('#new li').each(function(i,element) { + if ($(element).children('p').length === 0) { + $(element).children('form').remove(); + $(element).append('

'+$(element).data('text')+'

'); + } + }); + + var type=$(this).data('type'); + var text=$(this).children('p').text(); + $(this).data('text',text); + $(this).children('p').remove(); + + // add input field + var form = $('
'); + var input = $(''); + var newName = $(this).attr('data-newname') || ''; + if (newName) { + input.val(newName); + } + form.append(input); + $(this).append(form); + var lastPos; + var checkInput = function () { + var filename = input.val(); + if (type === 'web' && filename.length === 0) { + throw t('files', 'URL cannot be empty'); + } else if (type !== 'web' && !Files.isFileNameValid(filename)) { + // Files.isFileNameValid(filename) throws an exception itself + } else if (FileList.inList(filename)) { + throw t('files', '{new_name} already exists', {new_name: filename}); + } else { + return true; + } + }; + + // verify filename on typing + input.keyup(function(event) { + try { + checkInput(); + input.tipsy('hide'); + input.removeClass('error'); + } catch (error) { + input.attr('title', error); + input.tipsy({gravity: 'w', trigger: 'manual'}); + input.tipsy('show'); + input.addClass('error'); + } + }); + + input.focus(); + // pre select name up to the extension + lastPos = newName.lastIndexOf('.'); + if (lastPos === -1) { + lastPos = newName.length; + } + input.selectRange(0, lastPos); + form.submit(function(event) { + event.stopPropagation(); + event.preventDefault(); + try { + checkInput(); + var newname = input.val(); + if (FileList.lastAction) { + FileList.lastAction(); + } + var name = getUniqueName(newname); + if (newname !== name) { + FileList.checkName(name, newname, true); + var hidden = true; + } else { + var hidden = false; + } + switch(type) { + case 'file': + $.post( + OC.filePath('files', 'ajax', 'newfile.php'), + {dir:$('#dir').val(), filename:name}, + function(result) { + if (result.status === 'success') { + FileList.add(result.data, {hidden: hidden, animate: true}); + } else { + OC.dialogs.alert(result.data.message, t('core', 'Could not create file')); + } + } + ); + break; + case 'folder': + $.post( + OC.filePath('files','ajax','newfolder.php'), + {dir:$('#dir').val(), foldername:name}, + function(result) { + if (result.status === 'success') { + FileList.add(result.data, {hidden: hidden, animate: true}); + } else { + OC.dialogs.alert(result.data.message, t('core', 'Could not create folder')); + } + } + ); + break; + case 'web': + if (name.substr(0,8) !== 'https://' && name.substr(0,7) !== 'http://') { + name = 'http://' + name; + } + var localName=name; + if (localName.substr(localName.length-1,1)==='/') {//strip / + localName=localName.substr(0,localName.length-1); + } + if (localName.indexOf('/')) {//use last part of url + localName=localName.split('/').pop(); + } else { //or the domain + localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); + } + localName = getUniqueName(localName); + //IE < 10 does not fire the necessary events for the progress bar. + if ($('html.lte9').length === 0) { + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + } + + var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); + eventSource.listen('progress',function(progress) { + //IE < 10 does not fire the necessary events for the progress bar. + if ($('html.lte9').length === 0) { + $('#uploadprogressbar').progressbar('value',progress); + } + }); + eventSource.listen('success',function(data) { + var file = data; + $('#uploadprogressbar').fadeOut(); + + FileList.add(file, {hidden: hidden, animate: true}); + }); + eventSource.listen('error',function(error) { + $('#uploadprogressbar').fadeOut(); + var message = (error && error.message) || t('core', 'Error fetching URL'); + OC.Notification.show(message); + //hide notification after 10 sec + setTimeout(function() { + OC.Notification.hide(); + }, 10000); + }); + break; + } + var li=form.parent(); + form.remove(); + /* workaround for IE 9&10 click event trap, 2 lines: */ + $('input').first().focus(); + $('#content').focus(); + li.append('

'+li.data('text')+'

'); + $('#new>a').click(); + } catch (error) { + input.attr('title', error); + input.tipsy({gravity: 'w', trigger: 'manual'}); + input.tipsy('show'); + input.addClass('error'); + } + }); + }); + window.file_upload_param = file_upload_param; + return file_upload_param; } }; $(document).ready(function() { - - if ( $('#file_upload_start').exists() ) { - - var file_upload_param = { - dropZone: $('#content'), // restrict dropZone to content div - autoUpload: false, - sequentialUploads: true, - //singleFileUploads is on by default, so the data.files array will always have length 1 - /** - * on first add of every selection - * - check all files of originalFiles array with files in dir - * - on conflict show dialog - * - skip all -> remember as single skip action for all conflicting files - * - replace all -> remember as single replace action for all conflicting files - * - choose -> show choose dialog - * - mark files to keep - * - when only existing -> remember as single skip action - * - when only new -> remember as single replace action - * - when both -> remember as single autorename action - * - start uploading selection - * @param {object} e - * @param {object} data - * @returns {boolean} - */ - add: function(e, data) { - OC.Upload.log('add', e, data); - var that = $(this); - - // we need to collect all data upload objects before starting the upload so we can check their existence - // and set individual conflict actions. unfortunately there is only one variable that we can use to identify - // the selection a data upload is part of, so we have to collect them in data.originalFiles - // turning singleFileUploads off is not an option because we want to gracefully handle server errors like - // already exists - - // create a container where we can store the data objects - if ( ! data.originalFiles.selection ) { - // initialize selection and remember number of files to upload - data.originalFiles.selection = { - uploads: [], - filesToUpload: data.originalFiles.length, - totalBytes: 0 - }; - } - var selection = data.originalFiles.selection; - - // add uploads - if ( selection.uploads.length < selection.filesToUpload ) { - // remember upload - selection.uploads.push(data); - } - - //examine file - var file = data.files[0]; - try { - // FIXME: not so elegant... need to refactor that method to return a value - Files.isFileNameValid(file.name); - } - catch (errorMessage) { - data.textStatus = 'invalidcharacters'; - data.errorThrown = errorMessage; - } - - if (file.type === '' && file.size === 4096) { - data.textStatus = 'dirorzero'; - data.errorThrown = t('files', 'Unable to upload {filename} as it is a directory or has 0 bytes', - {filename: file.name} - ); - } - - // add size - selection.totalBytes += file.size; - - // check PHP upload limit - if (selection.totalBytes > $('#upload_limit').val()) { - data.textStatus = 'sizeexceedlimit'; - data.errorThrown = t('files', 'Total file size {size1} exceeds upload limit {size2}', { - 'size1': humanFileSize(selection.totalBytes), - 'size2': humanFileSize($('#upload_limit').val()) - }); - } - - // check free space - if (selection.totalBytes > $('#free_space').val()) { - data.textStatus = 'notenoughspace'; - data.errorThrown = t('files', 'Not enough free space, you are uploading {size1} but only {size2} is left', { - 'size1': humanFileSize(selection.totalBytes), - 'size2': humanFileSize($('#free_space').val()) - }); - } - - // end upload for whole selection on error - if (data.errorThrown) { - // trigger fileupload fail - var fu = that.data('blueimp-fileupload') || that.data('fileupload'); - fu._trigger('fail', e, data); - return false; //don't upload anything - } - - // check existing files when all is collected - if ( selection.uploads.length >= selection.filesToUpload ) { - - //remove our selection hack: - delete data.originalFiles.selection; - - var callbacks = { - - onNoConflicts: function (selection) { - $.each(selection.uploads, function(i, upload) { - upload.submit(); - }); - }, - onSkipConflicts: function (selection) { - //TODO mark conflicting files as toskip - }, - onReplaceConflicts: function (selection) { - //TODO mark conflicting files as toreplace - }, - onChooseConflicts: function (selection) { - //TODO mark conflicting files as chosen - }, - onCancel: function (selection) { - $.each(selection.uploads, function(i, upload) { - upload.abort(); - }); - } - }; - - OC.Upload.checkExistingFiles(selection, callbacks); - - } - - return true; // continue adding files - }, - /** - * called after the first add, does NOT have the data param - * @param {object} e - */ - start: function(e) { - OC.Upload.log('start', e, null); - }, - submit: function(e, data) { - OC.Upload.rememberUpload(data); - if ( ! data.formData ) { - // noone set update parameters, we set the minimum - data.formData = { - requesttoken: oc_requesttoken, - dir: $('#dir').val() - }; - } - }, - fail: function(e, data) { - OC.Upload.log('fail', e, data); - if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { - if (data.textStatus === 'abort') { - OC.Notification.show(t('files', 'Upload cancelled.')); - } else { - // HTTP connection problem - OC.Notification.show(data.errorThrown); - if (data.result) { - var result = JSON.parse(data.result); - if (result && result[0] && result[0].data && result[0].data.code === 'targetnotfound') { - // abort upload of next files if any - OC.Upload.cancelUploads(); - } - } - } - //hide notification after 10 sec - setTimeout(function() { - OC.Notification.hide(); - }, 10000); - } - OC.Upload.deleteUpload(data); - }, - /** - * called for every successful upload - * @param {object} e - * @param {object} data - */ - done:function(e, data) { - OC.Upload.log('done', e, data); - // handle different responses (json or body from iframe for ie) - var response; - if (typeof data.result === 'string') { - response = data.result; - } else { - //fetch response from iframe - response = data.result[0].body.innerText; - } - var result=$.parseJSON(response); - - delete data.jqXHR; - - if (result.status === 'error' && result.data && result.data.message){ - data.textStatus = 'servererror'; - data.errorThrown = result.data.message; - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } else if (typeof result[0] === 'undefined') { - data.textStatus = 'servererror'; - data.errorThrown = t('files', 'Could not get result from server.'); - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } else if (result[0].status === 'existserror') { - //show "file already exists" dialog - var original = result[0]; - var replacement = data.files[0]; - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - OC.dialogs.fileexists(data, original, replacement, OC.Upload, fu); - } else if (result[0].status !== 'success') { - //delete data.jqXHR; - data.textStatus = 'servererror'; - data.errorThrown = result[0].data.message; // error message has been translated on server - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - fu._trigger('fail', e, data); - } - }, - /** - * called after last upload - * @param {object} e - * @param {object} data - */ - stop: function(e, data) { - OC.Upload.log('stop', e, data); - } - }; - - // initialize jquery fileupload (blueimp) - var fileupload = $('#file_upload_start').fileupload(file_upload_param); - window.file_upload_param = fileupload; - - if (supportAjaxUploadWithProgress()) { - - // add progress handlers - fileupload.on('fileuploadadd', function(e, data) { - OC.Upload.log('progress handle fileuploadadd', e, data); - //show cancel button - //if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie? - // $('#uploadprogresswrapper input.stop').show(); - //} - }); - // add progress handlers - fileupload.on('fileuploadstart', function(e, data) { - OC.Upload.log('progress handle fileuploadstart', e, data); - $('#uploadprogresswrapper input.stop').show(); - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - }); - fileupload.on('fileuploadprogress', function(e, data) { - OC.Upload.log('progress handle fileuploadprogress', e, data); - //TODO progressbar in row - }); - fileupload.on('fileuploadprogressall', function(e, data) { - OC.Upload.log('progress handle fileuploadprogressall', e, data); - var progress = (data.loaded / data.total) * 100; - $('#uploadprogressbar').progressbar('value', progress); - }); - fileupload.on('fileuploadstop', function(e, data) { - OC.Upload.log('progress handle fileuploadstop', e, data); - - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - Files.updateStorageStatistics(); - }); - fileupload.on('fileuploadfail', function(e, data) { - OC.Upload.log('progress handle fileuploadfail', e, data); - //if user pressed cancel hide upload progress bar and cancel button - if (data.errorThrown === 'abort') { - $('#uploadprogresswrapper input.stop').fadeOut(); - $('#uploadprogressbar').fadeOut(); - } - }); - - } else { - console.log('skipping file progress because your browser is broken'); - } - } - - $.assocArraySize = function(obj) { - // http://stackoverflow.com/a/6700/11236 - var size = 0, key; - for (key in obj) { - if (obj.hasOwnProperty(key)) { - size++; - } - } - return size; - }; - - // warn user not to leave the page while upload is in progress - $(window).on('beforeunload', function(e) { - if (OC.Upload.isProcessing()) { - return t('files', 'File upload is in progress. Leaving the page now will cancel the upload.'); - } - }); - - //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) - if (navigator.userAgent.search(/konqueror/i) === -1) { - $('#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){ - return; - } - $('#new>ul').hide(); - $('#new').removeClass('active'); - if ($('#new .error').length > 0) { - $('#new .error').tipsy('hide'); - } - $('#new li').each(function(i,element) { - if ($(element).children('p').length === 0) { - $(element).children('form').remove(); - $(element).append('

'+$(element).data('text')+'

'); - } - }); - }); - $('#new').click(function(event) { - event.stopPropagation(); - }); - $('#new>a').click(function() { - $('#new>ul').toggle(); - $('#new').toggleClass('active'); - }); - $('#new li').click(function() { - if ($(this).children('p').length === 0) { - return; - } - - $('#new .error').tipsy('hide'); - - $('#new li').each(function(i,element) { - if ($(element).children('p').length === 0) { - $(element).children('form').remove(); - $(element).append('

'+$(element).data('text')+'

'); - } - }); - - var type=$(this).data('type'); - var text=$(this).children('p').text(); - $(this).data('text',text); - $(this).children('p').remove(); - - // add input field - var form = $('
'); - var input = $(''); - var newName = $(this).attr('data-newname') || ''; - if (newName) { - input.val(newName); - } - form.append(input); - $(this).append(form); - var lastPos; - var checkInput = function () { - var filename = input.val(); - if (type === 'web' && filename.length === 0) { - throw t('files', 'URL cannot be empty'); - } else if (type !== 'web' && !Files.isFileNameValid(filename)) { - // Files.isFileNameValid(filename) throws an exception itself - } else if ($('#dir').val() === '/' && filename === 'Shared') { - throw t('files', 'In the home folder \'Shared\' is a reserved filename'); - } else if (FileList.inList(filename)) { - throw t('files', '{new_name} already exists', {new_name: filename}); - } else { - return true; - } - }; - - // verify filename on typing - input.keyup(function(event) { - try { - checkInput(); - input.tipsy('hide'); - input.removeClass('error'); - } catch (error) { - input.attr('title', error); - input.tipsy({gravity: 'w', trigger: 'manual'}); - input.tipsy('show'); - input.addClass('error'); - } - }); - - input.focus(); - // pre select name up to the extension - lastPos = newName.lastIndexOf('.'); - if (lastPos === -1) { - lastPos = newName.length; - } - input.selectRange(0, lastPos); - form.submit(function(event) { - event.stopPropagation(); - event.preventDefault(); - try { - checkInput(); - var newname = input.val(); - if (FileList.lastAction) { - FileList.lastAction(); - } - var name = getUniqueName(newname); - if (newname !== name) { - FileList.checkName(name, newname, true); - var hidden = true; - } else { - var hidden = false; - } - switch(type) { - case 'file': - $.post( - OC.filePath('files', 'ajax', 'newfile.php'), - {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); - } else { - OC.dialogs.alert(result.data.message, t('core', 'Could not create file')); - } - } - ); - break; - case 'folder': - $.post( - OC.filePath('files','ajax','newfolder.php'), - {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); - } else { - OC.dialogs.alert(result.data.message, t('core', 'Could not create folder')); - } - } - ); - break; - case 'web': - if (name.substr(0,8) !== 'https://' && name.substr(0,7) !== 'http://') { - name = 'http://' + name; - } - var localName=name; - if (localName.substr(localName.length-1,1)==='/') {//strip / - localName=localName.substr(0,localName.length-1); - } - if (localName.indexOf('/')) {//use last part of url - localName=localName.split('/').pop(); - } else { //or the domain - localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); - } - localName = getUniqueName(localName); - //IE < 10 does not fire the necessary events for the progress bar. - if ($('html.lte9').length === 0) { - $('#uploadprogressbar').progressbar({value:0}); - $('#uploadprogressbar').fadeIn(); - } - - var eventSource=new OC.EventSource(OC.filePath('files','ajax','newfile.php'),{dir:$('#dir').val(),source:name,filename:localName}); - eventSource.listen('progress',function(progress) { - //IE < 10 does not fire the necessary events for the progress bar. - if ($('html.lte9').length === 0) { - $('#uploadprogressbar').progressbar('value',progress); - } - }); - eventSource.listen('success',function(data) { - var mime = data.mime; - var size = data.size; - var id = data.id; - $('#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); - }); - eventSource.listen('error',function(error) { - $('#uploadprogressbar').fadeOut(); - var message = (error && error.message) || t('core', 'Error fetching URL'); - OC.Notification.show(message); - //hide notification after 10 sec - setTimeout(function() { - OC.Notification.hide(); - }, 10000); - }); - break; - } - var li=form.parent(); - form.remove(); - /* workaround for IE 9&10 click event trap, 2 lines: */ - $('input').first().focus(); - $('#content').focus(); - li.append('

'+li.data('text')+'

'); - $('#new>a').click(); - } catch (error) { - input.attr('title', error); - input.tipsy({gravity: 'w', trigger: 'manual'}); - input.tipsy('show'); - input.addClass('error'); - } - }); - }); - window.file_upload_param = file_upload_param; + OC.Upload.init(); }); + + diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 9a69d7b368..ecdfa72a47 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,12 @@ var FileActions = { event.data.actionFunc(file); }; - var addAction = function (name, action) { - // NOTE: Temporary fix to prevent rename action in root of Shared directory - if (name === 'Rename' && $('#dir').val() === '/Shared') { - return true; - } + var addAction = function (name, action, displayName) { 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 +134,7 @@ var FileActions = { if (img.call) { img = img(file); } - var html = ''; + var html = ''; if (img) { html += ''; } @@ -133,8 +142,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 +150,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); + if(actions.Share){ + displayName = t('files', 'Share'); + addAction('Share', actions.Share, displayName); } // remove the existing delete action @@ -165,7 +176,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 +210,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); } @@ -208,7 +219,7 @@ $(document).ready(function () { $('#fileList tr').each(function () { FileActions.display($(this).children('td.filename')); }); - + $('#fileList').trigger(jQuery.Event("fileActionsReady")); }); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index d6cffde05d..8896a8e23a 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -8,175 +8,663 @@ * */ -/* global OC, t, n, FileList, FileActions, Files */ -/* global procesSelection, dragOptions, SVGSupport, replaceSVG */ -window.FileList={ +/* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */ +/* global dragOptions, folderDropOptions */ +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, + + /** + * Instance of FileSummary + */ + fileSummary: null, + initialized: false, + + // number of files per page + pageSize: 20, + + /** + * Array of files in the current folder. + * The entries are of file data. + */ + files: [], + + /** + * Map of file id to file data + */ + _selectedFiles: {}, + + /** + * Summary of selected files. + * Instance of FileSummary. + */ + _selectionSummary: null, + + /** + * Compare two file info objects, sorting by + * folders first, then by name. + */ + _fileInfoCompare: function(fileInfo1, fileInfo2) { + if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') { + return -1; + } + if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') { + return 1; + } + return fileInfo1.name.localeCompare(fileInfo2.name); + }, + + /** + * 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.files = []; + this._selectedFiles = {}; + this._selectionSummary = new FileSummary(); + + this.fileSummary = this._createSummary(); + + this.breadcrumb = new BreadCrumb({ + onClick: this._onClickBreadCrumb, + onDrop: _.bind(this._onDropOnBreadCrumb, this), + 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); + }); + + this.$fileList.on('click','td.filename>a.name', _.bind(this._onClickFile, this)); + this.$fileList.on('change', 'td.filename>input:checkbox', _.bind(this._onClickFileCheckbox, this)); + this.$el.find('#select_all').click(_.bind(this._onClickSelectAll, this)); + this.$el.find('.download').click(_.bind(this._onClickDownloadSelected, this)); + this.$el.find('.delete-selected').click(_.bind(this._onClickDeleteSelected, this)); + }, + + /** + * Selected/deselects the given file element and updated + * the internal selection cache. + * + * @param $tr single file row element + * @param state true to select, false to deselect + */ + _selectFileEl: function($tr, state) { + var $checkbox = $tr.find('td.filename>input:checkbox'); + var oldData = !!this._selectedFiles[$tr.data('id')]; + var data; + $checkbox.prop('checked', state); + $tr.toggleClass('selected', state); + // already selected ? + if (state === oldData) { + return; + } + data = this.elementToFile($tr); + if (state) { + this._selectedFiles[$tr.data('id')] = data; + this._selectionSummary.add(data); + } + else { + delete this._selectedFiles[$tr.data('id')]; + this._selectionSummary.remove(data); + } + this.$el.find('#select_all').prop('checked', this._selectionSummary.getTotal() === this.files.length); + }, + + /** + * Event handler for when clicking on files to select them + */ + _onClickFile: function(event) { + var $tr = $(event.target).closest('tr'); + if (event.ctrlKey || event.shiftKey) { + event.preventDefault(); + if (event.shiftKey) { + var $lastTr = $(this._lastChecked); + var lastIndex = $lastTr.index(); + var currentIndex = $tr.index(); + var $rows = this.$fileList.children('tr'); + + // last clicked checkbox below current one ? + if (lastIndex > currentIndex) { + var aux = lastIndex; + lastIndex = currentIndex; + currentIndex = aux; + } + + // auto-select everything in-between + for (var i = lastIndex + 1; i < currentIndex; i++) { + this._selectFileEl($rows.eq(i), true); + } + } + else { + this._lastChecked = $tr; + } + var $checkbox = $tr.find('td.filename>input:checkbox'); + this._selectFileEl($tr, !$checkbox.prop('checked')); + this.updateSelectionSummary(); + } else { + var filename = $tr.attr('data-file'); + var renaming = $tr.data('renaming'); + if (!renaming) { + FileActions.currentFile = $tr.find('td'); + var mime=FileActions.getCurrentMimeType(); + var type=FileActions.getCurrentType(); + var permissions = FileActions.getCurrentPermissions(); + var action=FileActions.getDefault(mime,type, permissions); + if (action) { + event.preventDefault(); + action(filename); + } + } + } + }, + + /** + * Event handler for when clicking on a file's checkbox + */ + _onClickFileCheckbox: function(e) { + var $tr = $(e.target).closest('tr'); + this._selectFileEl($tr, !$tr.hasClass('selected')); + this._lastChecked = $tr; + this.updateSelectionSummary(); + }, + + /** + * Event handler for when selecting/deselecting all files + */ + _onClickSelectAll: function(e) { + var checked = $(e.target).prop('checked'); + this.$fileList.find('td.filename>input:checkbox').prop('checked', checked) + .closest('tr').toggleClass('selected', checked); + this._selectedFiles = {}; + this._selectionSummary.clear(); + if (checked) { + for (var i = 0; i < this.files.length; i++) { + var fileData = this.files[i]; + this._selectedFiles[fileData.id] = fileData; + this._selectionSummary.add(fileData); + } + } + this.updateSelectionSummary(); + }, + + /** + * Event handler for when clicking on "Download" for the selected files + */ + _onClickDownloadSelected: function(event) { + var files; + var dir = this.getCurrentDirectory(); + if (this.isAllSelected()) { + files = OC.basename(dir); + dir = OC.dirname(dir) || '/'; + } + else { + files = _.pluck(this.getSelectedFiles(), 'name'); + } + OC.Notification.show(t('files','Your download is being prepared. This might take some time if the files are big.')); + OC.redirect(Files.getDownloadUrl(files, dir)); + return false; + }, + + /** + * Event handler for when clicking on "Delete" for the selected files + */ + _onClickDeleteSelected: function(event) { + var files = null; + if (!FileList.isAllSelected()) { + files = _.pluck(this.getSelectedFiles(), 'name'); + } + this.do_delete(files); + event.preventDefault(); + return 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); + } + }, + + _onScroll: function(e) { + if ($(window).scrollTop() + $(window).height() > $(document).height() - 500) { + this._nextPage(true); + } + }, + + /** + * Event handler when dropping on a breadcrumb + */ + _onDropOnBreadCrumb: function( event, ui ) { + var $target = $(event.target); + if (!$target.is('.crumb')) { + $target = $target.closest('.crumb'); + } + var targetPath = $(event.target).data('dir'); + var dir = this.getCurrentDirectory(); + while (dir.substr(0,1) === '/') {//remove extra leading /'s + dir = dir.substr(1); + } + dir = '/' + dir; + if (dir.substr(-1,1) !== '/') { + dir = dir + '/'; + } + // do nothing if dragged on current dir + if (targetPath === dir || targetPath + '/' === dir) { + return; + } + + var files = this.getSelectedFiles(); + if (files.length === 0) { + // single one selected without checkbox? + files = _.map(ui.helper.find('tr'), FileList.elementToFile); + } + + FileList.move(_.pluck(files, 'name'), targetPath); + }, + + /** + * Sets a new page title + */ + setPageTitle: function(title){ + if (title) { + title += ' - '; + } else { + title = ''; + } + title += FileList.appName; + // Sets the page title with the " - ownCloud" suffix as in templates + window.document.title = title + ' - ' + oc_defaults.title; + + return true; }, /** * 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(); + + /** + * Returns the file data from a given file element. + * @param $el file tr element + * @return file data + */ + elementToFile: function($el){ + $el = $($el); + return { + id: parseInt($el.attr('data-id'), 10), + name: $el.attr('data-file'), + mimetype: $el.attr('data-mime'), + type: $el.attr('data-type'), + size: parseInt($el.attr('data-size'), 10), + etag: $el.attr('data-etag') + }; + }, + + /** + * Appends the next page of files into the table + * @param animate true to animate the new elements + */ + _nextPage: function(animate) { + var index = this.$fileList.children().length, + count = this.pageSize, + tr, + fileData, + newTrs = [], + isAllSelected = this.isAllSelected(); + + if (index >= this.files.length) { + return; + } + + while (count > 0 && index < this.files.length) { + fileData = this.files[index]; + tr = this._renderRow(fileData, {updateSummary: false}); + this.$fileList.append(tr); + if (isAllSelected || this._selectedFiles[fileData.id]) { + tr.addClass('selected'); + tr.find('input:checkbox').prop('checked', true); + } + if (animate) { + tr.addClass('appear transparent'); + newTrs.push(tr); + } + index++; + count--; + } + + if (animate) { + // defer, for animation + window.setTimeout(function() { + for (var i = 0; i < newTrs.length; i++ ) { + newTrs[i].removeClass('transparent'); + } + }, 0); + } + }, + + /** + * Sets the files to be displayed in the list. + * This operation will re-render the list and update the summary. + * @param filesArray array of file data (map) + */ + setFiles: function(filesArray) { + // detach to make adding multiple rows faster + this.files = filesArray; + + this.$fileList.detach(); + this.$fileList.empty(); + + // clear "Select all" checkbox + this.$el.find('#select_all').prop('checked', false); + + this.isEmpty = this.files.length === 0; + this._nextPage(); + + 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(); - procesSelection(); + this.fileSummary.calculate(filesArray); + + FileList.updateSelectionSummary(); $(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'; + } + + // user should always be able to rename a share mount point + var allowRename = 0; + if (fileData.isShareMountPoint) { + allowRename = OC.PERMISSION_UPDATE; + } + //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 | allowRename || 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(''); - var link_elem = $('').attr({ - "class": "name", - "href": linktarget - }); - //split extension from filename for non dirs - if (type !== 'dir' && name.indexOf('.') !== -1) { - basename=name.substr(0,name.lastIndexOf('.')); - extension=name.substr(name.lastIndexOf('.')); - } else { - 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 + + // linkUrl if (type === 'dir') { - link_elem.append($('').attr({ + linkUrl = FileList.linkTo(FileList.getCurrentDirectory() + '/' + name); + } + else { + linkUrl = Files.getDownloadUrl(name, FileList.getCurrentDirectory()); + } + td.append(''); + var linkElem = $('').attr({ + "class": "name", + "href": linkUrl + }); + + // 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('.')); + } else { + basename = name; + extension = false; + } + var nameSpan=$('').addClass('nametext').text(basename); + linkElem.append(nameSpan); + if (extension) { + nameSpan.append($('').addClass('extension').text(extension)); + } + // dirs can show the number of uploaded files + if (type === 'dir') { + linkElem.append($('').attr({ 'class': 'uploadtext', 'currentUploads': 0 })); } - td.append(link_elem); + td.append(linkElem); 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); + 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; - if (!param) { - param = {}; + /** + * Adds an entry to the files array and also into the DOM + * in a sorted manner. + * + * @param fileData map of file attributes + * @param options map of attributes: + * - "updateSummary" true to update the summary after adding (default), false otherwise + * @return new tr element (not appended to the table) + */ + add: function(fileData, options) { + var index = -1; + var $tr; + var $rows; + var $insertionPoint; + options = options || {}; + + // there are three situations to cover: + // 1) insertion point is visible on the current page + // 2) insertion point is on a not visible page (visible after scrolling) + // 3) insertion point is at the end of the list + + $rows = this.$fileList.children(); + index = this._findInsertionIndex(fileData); + if (index > this.files.length) { + index = this.files.length; + } + else { + $insertionPoint = $rows.eq(index); } - var download_url = null; - if (!param.download_url) { - download_url = OC.Router.generate('download', { file: $('#dir').val()+'/'+name }); - } else { - download_url = param.download_url; + // is the insertion point visible ? + if ($insertionPoint.length) { + // only render if it will really be inserted + $tr = this._renderRow(fileData, options); + $insertionPoint.before($tr); + } + else { + // if insertion point is after the last visible + // entry, append + if (index === $rows.length) { + $tr = this._renderRow(fileData, options); + this.$fileList.append($tr); + } } - if (loading) { - imgurl = OC.imagePath('core', 'loading.gif'); - } else { - imgurl = OC.imagePath('core', 'filetypes/file.png'); + this.isEmpty = false; + this.files.splice(index, 0, fileData); + + if ($tr && options.animate) { + $tr.addClass('appear transparent'); + window.setTimeout(function() { + $tr.removeClass('transparent'); + }); } - var tr = this.createRow( - 'file', - name, - imgurl, - download_url, - size, - lastModified, - $('#permissions').val() + + // defaults to true if not defined + if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) { + this.fileSummary.add(fileData, true); + this.updateEmptyContent(); + } + + return $tr; + }, + + /** + * Creates a new row element based on the given attributes + * and returns it. + * + * @param fileData map of file attributes + * @param options map of attributes: + * - "index" optional index at which to insert the element + * - "updateSummary" true to update the summary after adding (default), false otherwise + * @return new tr element (not appended to the table) + */ + _renderRow: function(fileData, options) { + options = options || {}; + var type = fileData.type || 'file', + mime = fileData.mimetype, + permissions = parseInt(fileData.permissions, 10) || 0; + + if (fileData.isShareMountPoint) { + permissions = permissions | OC.PERMISSION_UPDATE; + } + + if (type === 'dir') { + mime = mime || 'httpd/unix-directory'; + } + var tr = this._createRow( + fileData, + options ); + var filenameTd = tr.find('td.filename'); - FileList.insertElement(name, 'file', tr); - if (loading) { - tr.data('loading', true); - } else { - tr.find('td.filename').draggable(dragOptions); + // TODO: move dragging to FileActions ? + // enable drag only for deletable files + if (permissions & OC.PERMISSION_DELETE) { + filenameTd.draggable(dragOptions); } - if (hidden) { - tr.hide(); + // allow dropping on folders + if (fileData.type === 'dir') { + filenameTd.droppable(folderDropOptions); + } + + if (options.hidden) { + tr.addClass('hidden'); + } + + // 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.png'), - 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(); - } - 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) @@ -185,26 +673,42 @@ window.FileList={ */ changeDirectory: function(targetDir, changeUrl, force) { var $dir = $('#dir'), - url, currentDir = $dir.val() || '/'; targetDir = targetDir || '/'; if (!force && currentDir === targetDir) { return; } - FileList.setCurrentDir(targetDir, changeUrl); + FileList._setCurrentDir(targetDir, changeUrl); $('#fileList').trigger( jQuery.Event('changeDirectory', { dir: targetDir, previousDir: currentDir } )); - FileList.reload(); + this._selectedFiles = {}; + this._selectionSummary.clear(); + this.reload(); }, linkTo: function(dir) { return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); }, - setCurrentDir: function(targetDir, changeUrl) { - var url; + + /** + * 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); + + if (baseDir !== '') { + FileList.setPageTitle(baseDir); + } + else { + FileList.setPageTitle(); + } + $('#dir').val(targetDir); if (changeUrl !== false) { if (window.history.pushState && changeUrl !== false) { @@ -216,6 +720,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 @@ -226,10 +731,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); @@ -240,10 +744,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); @@ -252,7 +754,11 @@ window.FileList={ if (result.status === 404) { // go back home - FileList.changeDirectory('/'); + this.changeDirectory('/'); + return; + } + // aborted ? + if (result.status === 0){ return; } @@ -261,24 +767,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; @@ -295,10 +787,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'); @@ -314,72 +810,135 @@ 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 + * @return deleted element + */ + remove: function(name, options){ + options = options || {}; var fileEl = FileList.findFileEl(name); + var index = fileEl.index(); + if (!fileEl.length) { + return null; + } + if (this._selectedFiles[fileEl.data('id')]) { + // remove from selection first + this._selectFileEl(fileEl, false); + this.updateSelectionSummary(); + } if (fileEl.data('permissions') & OC.PERMISSION_DELETE) { // file is only draggable when delete permissions are set fileEl.find('td.filename').draggable('destroy'); } + this.files.splice(index, 1); 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.files.length; + if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) { + FileList.updateEmptyContent(); + this.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}, true); } + + var lastIndex = this.$fileList.children().length; + // if there are less elements visible than one page + // but there are still pending elements in the array, + // then directly append the next page + if (lastIndex < this.files.length && lastIndex < this.pageSize) { + this._nextPage(true); + } + + 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'); - if (name.localeCompare($(fileElements[0]).attr('data-file')) < 0) { - pos = -1; - } else if (name.localeCompare($(fileElements[fileElements.length-1]).attr('data-file')) > 0) { - pos = fileElements.length - 1; - } else { - for(pos = 0; pos 0 - && name.localeCompare($(fileElements[pos+1]).attr('data-file')) < 0) + /** + * Finds the index of the row before which the given + * fileData should be inserted, considering the current + * sorting + */ + _findInsertionIndex: function(fileData) { + var index = 0; + while (index < this.files.length && this._fileInfoCompare(fileData, this.files[index]) > 0) { + index++; + } + return index; + }, + /** + * Moves a file to a given target folder. + * + * @param fileNames array of file names to move + * @param targetPath absolute target path + */ + move: function(fileNames, targetPath) { + var self = this; + var dir = this.getCurrentDirectory(); + var target = OC.basename(targetPath); + if (!_.isArray(fileNames)) { + fileNames = [fileNames]; + } + _.each(fileNames, function(fileName) { + var $tr = self.findFileEl(fileName); + var $td = $tr.children('td.filename'); + var oldBackgroundImage = $td.css('background-image'); + $td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); + // TODO: improve performance by sending all file names in a single call + $.post( + OC.filePath('files', 'ajax', 'move.php'), { - break; - } - } - } - if (fileElements.exists()) { - if (pos === -1) { - $(fileElements[0]).before(element); - } 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 { - $('#fileList').append(element); - } - $('#emptycontent').addClass('hidden'); - $('#filestable th').removeClass('hidden'); - FileList.updateFileSummary(); + dir: dir, + file: fileName, + target: targetPath + }, + function(result) { + if (result) { + if (result.status === 'success') { + // if still viewing the same directory + if (self.getCurrentDirectory() === dir) { + // recalculate folder size + var oldFile = self.findFileEl(target); + var newFile = self.findFileEl(fileName); + var oldSize = oldFile.data('size'); + var newSize = oldSize + newFile.data('size'); + oldFile.data('size', newSize); + oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize)); + + // TODO: also update entry in FileList.files + + self.remove(fileName); + } + } else { + OC.Notification.hide(); + if (result.status === 'error' && result.data.message) { + OC.Notification.show(result.data.message); + } + else { + OC.Notification.show(t('files', 'Error moving file.')); + } + // hide notification after 10 sec + setTimeout(function() { + OC.Notification.hide(); + }, 10000); + } + } else { + OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); + } + $td.css('background-image', oldBackgroundImage); + }); + }); + }, - 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) { + + /** + * Triggers file rename input field for the given file name. + * If the user enters a new name, the file will be renamed. + * + * @param oldname file name of the file to rename + */ + rename: function(oldname) { var tr, td, input, form; tr = FileList.findFileEl(oldname); + var oldFileInfo = this.files[tr.index()]; tr.data('renaming',true); td = tr.children('td.filename'); input = $('').val(oldname); @@ -390,19 +949,17 @@ window.FileList={ input.focus(); //preselect input var len = input.val().lastIndexOf('.'); - if (len === -1) { + if ( len === -1 || + tr.data('type') === 'dir' ) { len = input.val().length; } input.selectRange(0, len); - var checkInput = function () { var filename = input.val(); if (filename !== oldname) { - if (!Files.isFileNameValid(filename)) { - // Files.isFileNameValid(filename) throws an exception itself - } else if($('#dir').val() === '/' && filename === 'Shared') { - throw t('files','In the home folder \'Shared\' is a reserved filename'); - } else if (FileList.inList(filename)) { + // Files.isFileNameValid(filename) throws an exception itself + Files.isFileNameValid(filename); + if (FileList.inList(filename)) { throw t('files', '{new_name} already exists', {new_name: filename}); } } @@ -413,81 +970,50 @@ window.FileList={ event.stopPropagation(); event.preventDefault(); try { - var newname = input.val(); - if (newname !== oldname) { + var newName = input.val(); + if (newName !== oldname) { checkInput(); - // save background image, because it's replaced by a spinner while async request - var oldBackgroundImage = td.css('background-image'); // mark as loading td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); $.ajax({ url: OC.filePath('files','ajax','rename.php'), data: { dir : $('#dir').val(), - newname: newname, + newname: newName, file: oldname }, success: function(result) { + var fileInfo; if (!result || result.status === 'error') { OC.dialogs.alert(result.data.message, t('core', 'Could not rename file')); - // revert changes - newname = oldname; - tr.attr('data-file', 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 && tr.data('type') !== 'dir') { - basename = newname.substr(0,newname.lastIndexOf('.')); - } - td.find('a.name span.nametext').text(basename); - if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') { - if ( ! td.find('a.name span.extension').exists() ) { - td.find('a.name span.nametext').append(''); - } - td.find('a.name span.extension').text(newname.substr(newname.lastIndexOf('.'))); - } - tr.find('.fileactions').effect('highlight', {}, 5000); - tr.effect('highlight', {}, 5000); - // remove loading mark and recover old image - td.css('background-image', oldBackgroundImage); + fileInfo = oldFileInfo; } else { - var fileInfo = result.data; - 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) { - 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+')'); - } + fileInfo = result.data; } // reinsert row - tr.detach(); - FileList.insertElement( tr.attr('data-file'), tr.attr('data-type'),tr ); - // update file actions in case the extension changed - FileActions.display( tr.find('td.filename'), true); + FileList.files.splice(tr.index(), 1); + tr.remove(); + FileList.add(fileInfo); } }); } input.tipsy('hide'); tr.data('renaming',false); - tr.attr('data-file', newname); + tr.attr('data-file', newName); var path = td.children('a.name').attr('href'); // FIXME this will fail if the path contains the filename. - td.children('a.name').attr('href', path.replace(encodeURIComponent(oldname), encodeURIComponent(newname))); - var basename = newname; - if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') { - basename = newname.substr(0, newname.lastIndexOf('.')); + td.children('a.name').attr('href', path.replace(encodeURIComponent(oldname), encodeURIComponent(newName))); + var basename = newName; + if (newName.indexOf('.') > 0 && tr.data('type') !== 'dir') { + basename = newName.substr(0, newName.lastIndexOf('.')); } td.find('a.name span.nametext').text(basename); - if (newname.indexOf('.') > 0 && tr.data('type') !== 'dir') { + if (newName.indexOf('.') > 0 && tr.data('type') !== 'dir') { if ( ! td.find('a.name span.extension').exists() ) { td.find('a.name span.nametext').append(''); } - td.find('a.name span.extension').text(newname.substr(newname.lastIndexOf('.'))); + td.find('a.name span.extension').text(newName.substr(newName.lastIndexOf('.'))); } form.remove(); FileActions.display( tr.find('td.filename'), true); @@ -530,58 +1056,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) { @@ -598,7 +1078,7 @@ window.FileList={ FileList.lastAction(); } - var params = { + params = { dir: dir || FileList.getCurrentDirectory() }; if (files) { @@ -607,6 +1087,8 @@ window.FileList={ else { // no files passed, delete all in current dir params.allfiles = true; + // show spinner for all files + this.$fileList.find('tr>td.date .action.delete').removeClass('delete-icon').addClass('progress-icon'); } $.post(OC.filePath('files', 'ajax', 'delete.php'), @@ -614,21 +1096,23 @@ window.FileList={ function(result) { if (result.status === 'success') { if (params.allfiles) { - // clear whole list - $('#fileList tr').remove(); + FileList.setFiles([]); } 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}); + // FIXME: not sure why we need this after the + // element isn't even in the DOM any more + fileEl.find('input[type="checkbox"]').prop('checked', false); + fileEl.removeClass('selected'); + FileList.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}); }); } - procesSelection(); + // TODO: this info should be returned by the ajax call! checkTrashStatus(); - FileList.updateFileSummary(); FileList.updateEmptyContent(); + FileList.fileSummary.update(); + FileList.updateSelectionSummary(); Files.updateStorageStatistics(); } else { if (result.status === 'error' && result.data.message) { @@ -655,115 +1139,26 @@ window.FileList={ } }); }, - createFileSummary: function() { - if( $('#fileList tr').exists() ) { - var summary = this._calculateFileSummary(); + /** + * Creates the file summary section + */ + _createSummary: function() { + var $tr = $(''); + this.$el.find('tfoot').append($tr); - // Get translations - var directoryInfo = n('files', '%n folder', '%n folders', summary.totalDirs); - var fileInfo = n('files', '%n file', '%n files', summary.totalFiles); - - var infoVars = { - dirs: ''+directoryInfo+'', - files: ''+fileInfo+'' - }; - - var info = t('files', '{dirs} and {files}', infoVars); - - // don't show the filesize column, if filesize is NaN (e.g. in trashbin) - if (isNaN(summary.totalSize)) { - var fileSize = ''; - } else { - var fileSize = ''+humanFileSize(summary.totalSize)+''; - } - - var $summary = $(''+info+''+fileSize+''); - $('#fileList').append($summary); - - var $dirInfo = $summary.find('.dirinfo'); - var $fileInfo = $summary.find('.fileinfo'); - var $connector = $summary.find('.connector'); - - // Show only what's necessary, e.g.: no files: don't show "0 files" - if (summary.totalDirs === 0) { - $dirInfo.hide(); - $connector.hide(); - } - if (summary.totalFiles === 0) { - $fileInfo.hide(); - $connector.hide(); - } - } - }, - _calculateFileSummary: function() { - var result = { - totalDirs: 0, - totalFiles: 0, - totalSize: 0 - }; - $.each($('tr[data-file]'), function(index, value) { - var $value = $(value); - if ($value.data('type') === 'dir') { - result.totalDirs++; - } else if ($value.data('type') === 'file') { - result.totalFiles++; - } - if ($value.data('size') !== undefined && $value.data('id') !== -1) { - //Skip shared as it does not count toward quota - result.totalSize += parseInt($value.data('size')); - } - }); - return result; - }, - updateFileSummary: function() { - var $summary = $('.summary'); - - // Check if we should remove the summary to show "Upload something" - if ($('#fileList tr').length === 1 && $summary.length === 1) { - $summary.remove(); - } - // If there's no summary create one (createFileSummary checks if there's data) - else if ($summary.length === 0) { - FileList.createFileSummary(); - } - // There's a summary and data -> Update the summary - else if ($('#fileList tr').length > 1 && $summary.length === 1) { - var fileSummary = this._calculateFileSummary(); - var $dirInfo = $('.summary .dirinfo'); - var $fileInfo = $('.summary .fileinfo'); - var $connector = $('.summary .connector'); - - // Substitute old content with new translations - $dirInfo.html(n('files', '%n folder', '%n folders', fileSummary.totalDirs)); - $fileInfo.html(n('files', '%n file', '%n files', fileSummary.totalFiles)); - $('.summary .filesize').html(humanFileSize(fileSummary.totalSize)); - - // Show only what's necessary (may be hidden) - if (fileSummary.totalDirs === 0) { - $dirInfo.hide(); - $connector.hide(); - } else { - $dirInfo.show(); - } - if (fileSummary.totalFiles === 0) { - $fileInfo.hide(); - $connector.hide(); - } else { - $fileInfo.show(); - } - if (fileSummary.totalDirs > 0 && fileSummary.totalFiles > 0) { - $connector.show(); - } - } + return new FileSummary($tr); }, updateEmptyContent: function() { - 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'); @@ -771,38 +1166,38 @@ 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 - var $scrolltorow = FileList.findFileEl(file); - if ($scrolltorow.exists()) { - $scrolltorow.addClass('searchresult'); - $(window).scrollTop($scrolltorow.position().top); + var $scrollToRow = FileList.findFileEl(file); + if ($scrollToRow.exists()) { + $scrollToRow.addClass('searchresult'); + $(window).scrollTop($scrollToRow.position().top); //remove highlight when hovered over - $scrolltorow.one('hover', function() { - $scrolltorow.removeClass('searchresult'); + $scrollToRow.one('hover', function() { + $scrollToRow.removeClass('searchresult'); }); } }, filter:function(query) { - $('#fileList tr:not(.summary)').each(function(i,e) { + $('#fileList tr').each(function(i,e) { if ($(e).data('file').toString().toLowerCase().indexOf(query.toLowerCase()) !== -1) { $(e).addClass("searchresult"); } else { @@ -820,39 +1215,62 @@ window.FileList={ $(e).removeClass("searchresult"); }); }, + /** + * Update UI based on the current selection + */ + updateSelectionSummary: function() { + var summary = this._selectionSummary.summary; + if (summary.totalFiles === 0 && summary.totalDirs === 0) { + $('#headerName span.name').text(t('files','Name')); + $('#headerSize').text(t('files','Size')); + $('#modified').text(t('files','Modified')); + $('table').removeClass('multiselect'); + $('.selectedActions').addClass('hidden'); + } + else { + $('.selectedActions').removeClass('hidden'); + $('#headerSize').text(OC.Util.humanFileSize(summary.totalSize)); + var selection = ''; + if (summary.totalDirs > 0) { + selection += n('files', '%n folder', '%n folders', summary.totalDirs); + if (summary.totalFiles > 0) { + selection += ' & '; + } + } + if (summary.totalFiles > 0) { + selection += n('files', '%n file', '%n files', summary.totalFiles); + } + $('#headerName span.name').text(selection); + $('#modified').text(''); + $('table').addClass('multiselect'); + } + }, + /** * Returns whether all files are selected * @return true if all files are selected, false otherwise */ isAllSelected: function() { - return $('#select_all').prop('checked'); + return this.$el.find('#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 + * Returns the file info of the selected files + * + * @return array of file names */ - 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); + getSelectedFiles: function() { + return _.values(this._selectedFiles); } }; $(document).ready(function() { - var isPublic = !!$('#isPublic').val(); + FileList.initialize(); // handle upload events - var file_upload_start = $('#file_upload_start'); + var fileUploadStart = $('#file_upload_start'); - file_upload_start.on('fileuploaddrop', function(e, data) { + fileUploadStart.on('fileuploaddrop', function(e, data) { OC.Upload.log('filelist handle fileuploaddrop', e, data); var dropTarget = $(e.originalEvent.target).closest('tr, .crumb'); @@ -879,13 +1297,19 @@ $(document).ready(function() { data.formData = function(form) { return [ {name: 'dir', value: dir}, - {name: 'requesttoken', value: oc_requesttoken} + {name: 'requesttoken', value: oc_requesttoken}, + {name: 'file_directory', value: data.files[0].relativePath} ]; }; + } 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) { + fileUploadStart.on('fileuploadadd', function(e, data) { OC.Upload.log('filelist handle fileuploadadd', e, data); //finish delete if we are uploading a deleted file @@ -898,19 +1322,19 @@ $(document).ready(function() { // add to existing folder // update upload counter ui - var uploadtext = data.context.find('.uploadtext'); - var currentUploads = parseInt(uploadtext.attr('currentUploads')); + var uploadText = data.context.find('.uploadtext'); + var currentUploads = parseInt(uploadText.attr('currentUploads'), 10); currentUploads += 1; - uploadtext.attr('currentUploads', currentUploads); + uploadText.attr('currentUploads', currentUploads); var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads); if (currentUploads === 1) { var img = OC.imagePath('core', 'loading.gif'); data.context.find('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.text(translatedText); - uploadtext.show(); + uploadText.text(translatedText); + uploadText.show(); } else { - uploadtext.text(translatedText); + uploadText.text(translatedText); } } @@ -919,7 +1343,7 @@ $(document).ready(function() { * when file upload done successfully add row to filelist * update counter when uploading to sub folder */ - file_upload_start.on('fileuploaddone', function(e, data) { + fileUploadStart.on('fileuploaddone', function(e, data) { OC.Upload.log('filelist handle fileuploaddone', e, data); var response; @@ -933,130 +1357,119 @@ $(document).ready(function() { if (typeof result[0] !== 'undefined' && result[0].status === 'success') { var file = result[0]; + var size = 0; if (data.context && data.context.data('type') === 'dir') { // update upload counter ui - var uploadtext = data.context.find('.uploadtext'); - var currentUploads = parseInt(uploadtext.attr('currentUploads')); + var uploadText = data.context.find('.uploadtext'); + var currentUploads = parseInt(uploadText.attr('currentUploads'), 10); currentUploads -= 1; - uploadtext.attr('currentUploads', currentUploads); + uploadText.attr('currentUploads', currentUploads); var translatedText = n('files', 'Uploading %n file', 'Uploading %n files', currentUploads); if (currentUploads === 0) { - var img = OC.imagePath('core', 'filetypes/folder.png'); + var img = OC.imagePath('core', 'filetypes/folder'); data.context.find('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.text(translatedText); - uploadtext.hide(); + uploadText.text(translatedText); + uploadText.hide(); } else { - uploadtext.text(translatedText); + uploadText.text(translatedText); } // update folder size - var size = parseInt(data.context.data('size')); - size += parseInt(file.size); + size = parseInt(data.context.data('size'), 10); + size += parseInt(file.size, 10); data.context.attr('data-size', size); data.context.find('td.filesize').text(humanFileSize(size)); - } else { // only append new file if uploaded into the current folder - if (file.directory !== FileList.getCurrentDirectory()) { + if (file.directory !== '/' && file.directory !== FileList.getCurrentDirectory()) { + + var fileDirectory = file.directory.replace('/','').replace(/\/$/, "").split('/'); + + if (fileDirectory.length === 1) { + fileDirectory = fileDirectory[0]; + + // Get the directory + var fd = FileList.findFileEl(fileDirectory); + if (fd.length === 0) { + var dir = { + name: fileDirectory, + type: 'dir', + mimetype: 'httpd/unix-directory', + permissions: file.permissions, + size: 0, + id: file.parentId + }; + FileList.add(dir, {insert: true}); + } + } else { + fileDirectory = fileDirectory[0]; + } + + fileDirectory = FileList.findFileEl(fileDirectory); + + // update folder size + size = parseInt(fileDirectory.attr('data-size'), 10); + size += parseInt(file.size, 10); + fileDirectory.attr('data-size', size); + fileDirectory.find('td.filesize').text(humanFileSize(size)); + return; } // add as stand-alone row to filelist - var size=t('files', 'Pending'); + size = t('files', 'Pending'); 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, {animate: true}); } } }); - file_upload_start.on('fileuploadstop', function(e, data) { + fileUploadStart.on('fileuploadstop', function(e, data) { OC.Upload.log('filelist handle fileuploadstop', e, data); //if user pressed cancel hide upload chrome if (data.errorThrown === 'abort') { //cleanup uploading to a dir - var uploadtext = $('tr .uploadtext'); - var img = OC.imagePath('core', 'filetypes/folder.png'); - uploadtext.parents('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.fadeOut(); - uploadtext.attr('currentUploads', 0); + var uploadText = $('tr .uploadtext'); + var img = OC.imagePath('core', 'filetypes/folder'); + uploadText.parents('td.filename').attr('style','background-image:url('+img+')'); + uploadText.fadeOut(); + uploadText.attr('currentUploads', 0); } }); - file_upload_start.on('fileuploadfail', function(e, data) { + fileUploadStart.on('fileuploadfail', function(e, data) { OC.Upload.log('filelist handle fileuploadfail', e, data); //if user pressed cancel hide upload chrome if (data.errorThrown === 'abort') { //cleanup uploading to a dir - var uploadtext = $('tr .uploadtext'); - var img = OC.imagePath('core', 'filetypes/folder.png'); - uploadtext.parents('td.filename').attr('style','background-image:url('+img+')'); - uploadtext.fadeOut(); - uploadtext.attr('currentUploads', 0); + var uploadText = $('tr .uploadtext'); + var img = OC.imagePath('core', 'filetypes/folder'); + uploadText.parents('td.filename').attr('style','background-image:url('+img+')'); + uploadText.fadeOut(); + uploadText.attr('currentUploads', 0); } }); $('#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')); + FileList.replace( + $('#notification > span').attr('data-oldName'), + $('#notification > span').attr('data-newName'), + $('#notification > span').attr('data-isNewFile')); }); }); $('#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() { @@ -1081,8 +1494,7 @@ $(document).ready(function() { function parseHashQuery() { var hash = window.location.hash, - pos = hash.indexOf('?'), - query; + pos = hash.indexOf('?'); if (pos >= 0) { return hash.substr(pos + 1); } @@ -1091,8 +1503,7 @@ $(document).ready(function() { function parseCurrentDirFromUrl() { var query = parseHashQuery(), - params, - dir = '/'; + params; // try and parse from URL hash first if (query) { params = OC.parseQueryString(decodeQuery(query)); @@ -1105,32 +1516,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); - }); - } - 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); - } + // 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; + } + else{ + // read from URL + targetDir = parseCurrentDirFromUrl(); + } + if (targetDir) { + FileList.changeDirectory(targetDir, false); + } + }; - FileList.createFileSummary(); + $(window).scroll(function(e) {FileList._onScroll(e);}); + + var dir = parseCurrentDirFromUrl(); + // trigger ajax load, deferred to let sub-apps do their overrides first + setTimeout(function() { + FileList.changeDirectory(dir, false, true); + }, 0); }); + diff --git a/apps/files/js/files.js b/apps/files/js/files.js index fbac601f67..6d167851e6 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -8,8 +8,8 @@ * */ -/* global OC, t, n, FileList, FileActions */ -/* global getURLParameter, isPublic */ +/* global OC, t, FileList */ +/* global getURLParameter */ var Files = { // file space size sync _updateStorageStatistics: function() { @@ -89,16 +89,17 @@ var Files = { */ isFileNameValid: function (name) { var trimmedName = name.trim(); - if (trimmedName === '.' || trimmedName === '..') { + if (trimmedName === '.' || trimmedName === '..') + { throw t('files', '"{name}" is an invalid file name.', {name: name}); } else if (trimmedName.length === 0) { throw t('files', 'File name cannot be empty.'); } // check for invalid characters - var invalid_characters = + var invalidCharacters = ['\\', '/', '<', '>', ':', '"', '|', '?', '*', '\n']; - for (var i = 0; i < invalid_characters.length; i++) { - if (trimmedName.indexOf(invalid_characters[i]) !== -1) { + for (var i = 0; i < invalidCharacters.length; i++) { + if (trimmedName.indexOf(invalidCharacters[i]) !== -1) { throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."); } } @@ -115,7 +116,8 @@ var Files = { return; } if (usedSpacePercent > 90) { - OC.Notification.show(t('files', 'Your storage is almost full ({usedSpacePercent}%)', {usedSpacePercent: usedSpacePercent})); + OC.Notification.show(t('files', 'Your storage is almost full ({usedSpacePercent}%)', + {usedSpacePercent: usedSpacePercent})); } }, @@ -128,19 +130,20 @@ 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.show(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; } }, + // TODO: move to FileList class setupDragAndDrop: function() { var $fileList = $('#fileList'); @@ -158,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() { @@ -239,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'); @@ -256,7 +211,7 @@ $(document).ready(function() { // Trigger cancelling of file upload $('#uploadprogresswrapper .stop').on('click', function() { OC.Upload.cancelUploads(); - procesSelection(); + FileList.updateSelectionSummary(); }); // Show trash bin @@ -264,149 +219,15 @@ $(document).ready(function() { window.location=OC.filePath('files_trashbin', '', 'index.php'); }); - var lastChecked; - - // Sets the file link behaviour : - $('#fileList').on('click','td.filename a',function(event) { - if (event.ctrlKey || event.shiftKey) { - event.preventDefault(); - if (event.shiftKey) { - var last = $(lastChecked).parent().parent().prevAll().length; - var first = $(this).parent().parent().prevAll().length; - var start = Math.min(first, last); - var end = Math.max(first, last); - var rows = $(this).parent().parent().parent().children('tr'); - for (var i = start; i < end; i++) { - $(rows).each(function(index) { - if (index === i) { - var checkbox = $(this).children().children('input:checkbox'); - $(checkbox).attr('checked', 'checked'); - $(checkbox).parent().parent().addClass('selected'); - } - }); - } - } - var checkbox = $(this).parent().children('input:checkbox'); - lastChecked = checkbox; - if ($(checkbox).attr('checked')) { - $(checkbox).removeAttr('checked'); - $(checkbox).parent().parent().removeClass('selected'); - $('#select_all').removeAttr('checked'); - } else { - $(checkbox).attr('checked', 'checked'); - $(checkbox).parent().parent().toggleClass('selected'); - var selectedCount = $('td.filename input:checkbox:checked').length; - if (selectedCount === $('td.filename input:checkbox').length) { - $('#select_all').attr('checked', 'checked'); - } - } - procesSelection(); - } else { - var filename=$(this).parent().parent().attr('data-file'); - var tr = FileList.findFileEl(filename); - var renaming=tr.data('renaming'); - if (!renaming && !FileList.isLoading(filename)) { - FileActions.currentFile = $(this).parent(); - var mime=FileActions.getCurrentMimeType(); - var type=FileActions.getCurrentType(); - var permissions = FileActions.getCurrentPermissions(); - var action=FileActions.getDefault(mime,type, permissions); - if (action) { - event.preventDefault(); - action(filename); - } - } - } - - }); - - // Sets the select_all checkbox behaviour : - $('#select_all').click(function() { - if ($(this).attr('checked')) { - // Check all - $('td.filename input:checkbox').attr('checked', true); - $('td.filename input:checkbox').parent().parent().addClass('selected'); - } else { - // Uncheck all - $('td.filename input:checkbox').attr('checked', false); - $('td.filename input:checkbox').parent().parent().removeClass('selected'); - } - procesSelection(); - }); - - $('#fileList').on('change', 'td.filename input:checkbox',function(event) { - if (event.shiftKey) { - var last = $(lastChecked).parent().parent().prevAll().length; - var first = $(this).parent().parent().prevAll().length; - var start = Math.min(first, last); - var end = Math.max(first, last); - var rows = $(this).parent().parent().parent().children('tr'); - for (var i = start; i < end; i++) { - $(rows).each(function(index) { - if (index === i) { - var checkbox = $(this).children().children('input:checkbox'); - $(checkbox).attr('checked', 'checked'); - $(checkbox).parent().parent().addClass('selected'); - } - }); - } - } - var selectedCount=$('td.filename input:checkbox:checked').length; - $(this).parent().parent().toggleClass('selected'); - if (!$(this).attr('checked')) { - $('#select_all').attr('checked',false); - } else { - if (selectedCount===$('td.filename input:checkbox').length) { - $('#select_all').attr('checked',true); - } - } - procesSelection(); - }); - - $('.download').click('click',function(event) { - var files; - var dir = FileList.getCurrentDirectory(); - if (FileList.isAllSelected()) { - files = OC.basename(dir); - dir = OC.dirname(dir) || '/'; - } - else { - files = getSelectedFilesTrash('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)); - return false; - }); - - $('.delete-selected').click(function(event) { - var files=getSelectedFilesTrash('name'); - event.preventDefault(); - if (FileList.isAllSelected()) { - files = null; - } - FileList.do_delete(files); - return false; - }); - // drag&drop support using jquery.fileupload // TODO use OC.dialogs $(document).bind('drop dragover', function (e) { e.preventDefault(); // prevent browser from doing anything, if file isn't dropped in dropZone - }); + }); //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); @@ -479,34 +300,22 @@ function scanFiles(force, dir, users) { } scanFiles.scanning=false; -function boolOperationFinished(data, callback) { - result = jQuery.parseJSON(data.responseText); - Files.updateMaxUploadFilesize(result); - if (result.status === 'success') { - callback.call(); - } else { - alert(result.data.message); - } -} - +// TODO: move to FileList var createDragShadow = function(event) { //select dragged file var isDragSelected = $(event.target).parents('tr').find('td input:first').prop('checked'); if (!isDragSelected) { //select dragged file - $(event.target).parents('tr').find('td input:first').prop('checked',true); + FileList._selectFileEl($(event.target).parents('tr:first'), true); } - var selectedFiles = getSelectedFilesTrash(); + // do not show drag shadow for too many files + var selectedFiles = _.first(FileList.getSelectedFiles(), FileList.pageSize); + selectedFiles.sort(FileList._fileInfoCompare); if (!isDragSelected && selectedFiles.length === 1) { //revert the selection - $(event.target).parents('tr').find('td input:first').prop('checked',false); - } - - //also update class when we dragged more than one file - if (selectedFiles.length > 1) { - $(event.target).parents('tr').addClass('selected'); + FileList._selectFileEl($(event.target).parents('tr:first'), false); } // build dragshadow @@ -517,9 +326,12 @@ var createDragShadow = function(event) { var dir=$('#dir').val(); $(selectedFiles).each(function(i,elem) { - var newtr = $('').attr('data-dir', dir).attr('data-filename', elem.name).attr('data-origin', elem.origin); + var newtr = $('') + .attr('data-dir', dir) + .attr('data-file', elem.name) + .attr('data-origin', elem.origin); newtr.append($('').addClass('filename').text(elem.name)); - newtr.append($('').addClass('size').text(humanFileSize(elem.size))); + newtr.append($('').addClass('size').text(OC.Util.humanFileSize(elem.size))); tbody.append(newtr); if (elem.type === 'dir') { newtr.find('td.filename').attr('style','background-image:url('+OC.imagePath('core', 'filetypes/folder.png')+')'); @@ -536,204 +348,66 @@ var createDragShadow = function(event) { //options for file drag/drop //start&stop handlers needs some cleaning up +// TODO: move to FileList class var dragOptions={ revert: 'invalid', revertDuration: 300, opacity: 0.7, zIndex: 100, appendTo: 'body', cursorAt: { left: 24, top: 18 }, helper: createDragShadow, cursor: 'move', - start: function(event, ui){ - var $selectedFiles = $('td.filename input:checkbox:checked'); - if($selectedFiles.length > 1){ - $selectedFiles.parents('tr').fadeTo(250, 0.2); - } - else{ - $(this).fadeTo(250, 0.2); - } - }, - stop: function(event, ui) { - var $selectedFiles = $('td.filename input:checkbox:checked'); - if($selectedFiles.length > 1){ - $selectedFiles.parents('tr').fadeTo(250, 1); - } - else{ - $(this).fadeTo(250, 1); - } - $('#fileList tr td.filename').addClass('ui-draggable'); + start: function(event, ui){ + var $selectedFiles = $('td.filename input:checkbox:checked'); + if($selectedFiles.length > 1){ + $selectedFiles.parents('tr').fadeTo(250, 0.2); } + else{ + $(this).fadeTo(250, 0.2); + } + }, + stop: function(event, ui) { + var $selectedFiles = $('td.filename input:checkbox:checked'); + if($selectedFiles.length > 1){ + $selectedFiles.parents('tr').fadeTo(250, 1); + } + else{ + $(this).fadeTo(250, 1); + } + $('#fileList tr td.filename').addClass('ui-draggable'); + } }; // sane browsers support using the distance option if ( $('html.ie').length === 0) { dragOptions['distance'] = 20; } -var folderDropOptions={ +// TODO: move to FileList class +var folderDropOptions = { hoverClass: "canDrop", drop: function( event, ui ) { - //don't allow moving a file into a selected folder + // don't allow moving a file into a selected folder if ($(event.target).parents('tr').find('td input:first').prop('checked') === true) { return false; } - var target = $(this).closest('tr').data('file'); + var targetPath = FileList.getCurrentDirectory() + '/' + $(this).closest('tr').data('file'); - 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: dir+'/'+target }, function(result) { - if (result) { - if (result.status === 'success') { - //recalculate folder size - var oldFile = FileList.findFileEl(target); - var newFile = FileList.findFileEl(file); - var oldSize = oldFile.data('size'); - var newSize = oldSize + newFile.data('size'); - oldFile.data('size', newSize); - oldFile.find('td.filesize').text(humanFileSize(newSize)); + var files = FileList.getSelectedFiles(); + if (files.length === 0) { + // single one selected without checkbox? + files = _.map(ui.helper.find('tr'), FileList.elementToFile); + } - 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); - }); - }); + FileList.move(_.pluck(files, 'name'), targetPath); }, 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 selectedFiles = selected.filter(function(el) { - return el.type==='file'; - }); - var selectedFolders = selected.filter(function(el) { - return el.type==='dir'; - }); - if (selectedFiles.length === 0 && selectedFolders.length === 0) { - $('#headerName span.name').text(t('files','Name')); - $('#headerSize').text(t('files','Size')); - $('#modified').text(t('files','Modified')); - $('table').removeClass('multiselect'); - $('.selectedActions').hide(); - $('#select_all').removeAttr('checked'); - } - else { - $('.selectedActions').show(); - var totalSize = 0; - for(var i=0; i 0) { - selection += n('files', '%n folder', '%n folders', selectedFolders.length); - if (selectedFiles.length > 0) { - selection += ' & '; - } - } - if (selectedFiles.length>0) { - selection += n('files', '%n file', '%n files', selectedFiles.length); - } - $('#headerName span.name').text(selection); - $('#modified').text(''); - $('table').addClass('multiselect'); - } -} - -/** - * @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 getSelectedFilesTrash(property) { - var elements=$('td.filename input:checkbox:checked').parent().parent(); - var files=[]; - elements.each(function(i,element) { - var file={ - name:$(element).attr('data-file'), - mime:$(element).data('mime'), - type:$(element).data('type'), - size:$(element).data('size'), - etag:$(element).data('etag'), - origin: $(element).data('id') - }; - if (property) { - files.push(file[property]); - } else { - files.push(file); - } - }); - return files; -} - Files.getMimeIcon = function(mime, ready) { if (Files.getMimeIcon.cache[mime]) { ready(Files.getMimeIcon.cache[mime]); } else { $.get( OC.filePath('files','ajax','mimeicon.php'), {mime: mime}, function(path) { + if(OC.Util.hasSVGSupport()){ + path = path.substr(0, path.length-4) + '.svg'; + } Files.getMimeIcon.cache[mime]=path; ready(Files.getMimeIcon.cache[mime]); }); @@ -746,25 +420,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){ @@ -775,12 +456,7 @@ 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.Router.generate('core_ajax_public_preview', urlSpec); - } else { - previewURL = OC.Router.generate('core_ajax_preview', urlSpec); - } + previewURL = Files.generatePreviewUrl(urlSpec); previewURL = previewURL.replace('(', '%28'); previewURL = previewURL.replace(')', '%29'); @@ -788,9 +464,11 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { // this will make the browser cache the image var img = new Image(); img.onload = function(){ - //set preview thumbnail URL - ready(previewURL); - } + // if loading the preview image failed (no preview for the mimetype) then img.width will < 5 + if (img.width > 5) { + ready(previewURL); + } + }; img.src = previewURL; }); }; @@ -829,14 +507,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/js/filesummary.js b/apps/files/js/filesummary.js new file mode 100644 index 0000000000..b5130247cc --- /dev/null +++ b/apps/files/js/filesummary.js @@ -0,0 +1,195 @@ +/** +* 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, n, t */ + +(function() { + /** + * The FileSummary class encapsulates the file summary values and + * the logic to render it in the given container + * @param $tr table row element + * $param summary optional initial summary value + */ + var FileSummary = function($tr) { + this.$el = $tr; + this.clear(); + this.render(); + }; + + FileSummary.prototype = { + summary: { + totalFiles: 0, + totalDirs: 0, + totalSize: 0 + }, + + /** + * Adds file + * @param file file to add + * @param update whether to update the display + */ + add: function(file, update) { + if (file.type === 'dir' || file.mime === 'httpd/unix-directory') { + this.summary.totalDirs++; + } + else { + this.summary.totalFiles++; + } + this.summary.totalSize += parseInt(file.size, 10) || 0; + if (!!update) { + this.update(); + } + }, + /** + * Removes file + * @param file file to remove + * @param update whether to update the display + */ + remove: function(file, update) { + if (file.type === 'dir' || file.mime === 'httpd/unix-directory') { + this.summary.totalDirs--; + } + else { + this.summary.totalFiles--; + } + this.summary.totalSize -= parseInt(file.size, 10) || 0; + if (!!update) { + this.update(); + } + }, + /** + * Returns the total of files and directories + */ + getTotal: function() { + return this.summary.totalDirs + this.summary.totalFiles; + }, + /** + * Recalculates the summary based on the given files array + * @param files array of files + */ + calculate: function(files) { + var file; + var summary = { + totalDirs: 0, + totalFiles: 0, + totalSize: 0 + }; + + for (var i = 0; i < files.length; i++) { + file = files[i]; + if (file.type === 'dir' || file.mime === 'httpd/unix-directory') { + summary.totalDirs++; + } + else { + summary.totalFiles++; + } + summary.totalSize += parseInt(file.size, 10) || 0; + } + this.setSummary(summary); + }, + /** + * Clears the summary + */ + clear: function() { + this.calculate([]); + }, + /** + * Sets the current summary values + * @param summary map + */ + setSummary: function(summary) { + this.summary = summary; + this.update(); + }, + + /** + * Renders the file summary element + */ + update: function() { + if (!this.$el) { + return; + } + if (!this.summary.totalFiles && !this.summary.totalDirs) { + this.$el.addClass('hidden'); + return; + } + // There's a summary and data -> Update the summary + this.$el.removeClass('hidden'); + var $dirInfo = this.$el.find('.dirinfo'); + var $fileInfo = this.$el.find('.fileinfo'); + var $connector = this.$el.find('.connector'); + + // Substitute old content with new translations + $dirInfo.html(n('files', '%n folder', '%n folders', this.summary.totalDirs)); + $fileInfo.html(n('files', '%n file', '%n files', this.summary.totalFiles)); + this.$el.find('.filesize').html(OC.Util.humanFileSize(this.summary.totalSize)); + + // Show only what's necessary (may be hidden) + if (this.summary.totalDirs === 0) { + $dirInfo.addClass('hidden'); + $connector.addClass('hidden'); + } else { + $dirInfo.removeClass('hidden'); + } + if (this.summary.totalFiles === 0) { + $fileInfo.addClass('hidden'); + $connector.addClass('hidden'); + } else { + $fileInfo.removeClass('hidden'); + } + if (this.summary.totalDirs > 0 && this.summary.totalFiles > 0) { + $connector.removeClass('hidden'); + } + }, + render: function() { + if (!this.$el) { + return; + } + // TODO: ideally this should be separate to a template or something + var summary = this.summary; + var directoryInfo = n('files', '%n folder', '%n folders', summary.totalDirs); + var fileInfo = n('files', '%n file', '%n files', summary.totalFiles); + + var infoVars = { + dirs: ''+directoryInfo+'', + files: ''+fileInfo+'' + }; + + // don't show the filesize column, if filesize is NaN (e.g. in trashbin) + var fileSize = ''; + if (!isNaN(summary.totalSize)) { + fileSize = '' + OC.Util.humanFileSize(summary.totalSize) + ''; + } + + var info = t('files', '{dirs} and {files}', infoVars); + + var $summary = $(''+info+''+fileSize+''); + + if (!this.summary.totalFiles && !this.summary.totalDirs) { + this.$el.addClass('hidden'); + } + + this.$el.append($summary); + } + }; + window.FileSummary = FileSummary; +})(); + diff --git a/apps/files/js/upgrade.js b/apps/files/js/upgrade.js deleted file mode 100644 index 714adf824a..0000000000 --- a/apps/files/js/upgrade.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2014 - * - * This file is licensed under the Affero General Public License version 3 - * or later. - * - * See the COPYING-README file. - * - */ - -/* global OC */ -$(document).ready(function () { - var eventSource, total, bar = $('#progressbar'); - console.log('start'); - bar.progressbar({value: 0}); - eventSource = new OC.EventSource(OC.filePath('files', 'ajax', 'upgrade.php')); - eventSource.listen('total', function (count) { - total = count; - console.log(count + ' files needed to be migrated'); - }); - eventSource.listen('count', function (count) { - bar.progressbar({value: (count / total) * 100}); - console.log(count); - }); - eventSource.listen('done', function () { - document.location.reload(); - }); -}); diff --git a/apps/files/l10n/af_ZA.php b/apps/files/l10n/af_ZA.php index 0157af093e..62c4ec70ac 100644 --- a/apps/files/l10n/af_ZA.php +++ b/apps/files/l10n/af_ZA.php @@ -1,5 +1,6 @@ "Deel", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("","") diff --git a/apps/files/l10n/am_ET.php b/apps/files/l10n/am_ET.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/am_ET.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ar.php b/apps/files/l10n/ar.php index 0148f5ca3c..6779141c5e 100644 --- a/apps/files/l10n/ar.php +++ b/apps/files/l10n/ar.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "فشل في نقل الملف %s - يوجد ملف بنفس هذا الاسم", "Could not move %s" => "فشل في نقل %s", "File name cannot be empty." => "اسم الملف لا يجوز أن يكون فارغا", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "اسم غير صحيح , الرموز '\\', '/', '<', '>', ':', '\"', '|', '?' و \"*\" غير مسموح استخدامها", "Unable to set upload directory." => "غير قادر على تحميل المجلد", "Invalid Token" => "علامة غير صالحة", "No file was uploaded. Unknown error" => "لم يتم رفع أي ملف , خطأ غير معروف", @@ -14,12 +15,11 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "المجلد المؤقت غير موجود", "Failed to write to disk" => "خطأ في الكتابة على القرص الصلب", "Not enough storage available" => "لا يوجد مساحة تخزينية كافية", -"Upload failed. Could not get file info." => "فشلت عملية الرفع. تعذر الحصول على معلومات الملف.", "Upload failed. Could not find uploaded file" => "*فشلت علمية الرفع. تعذر إيجاد الملف الذي تم رفعه.\n*فشلت علمية التحميل. تعذر إيجاد الملف الذي تم تحميله.", +"Upload failed. Could not get file info." => "فشلت عملية الرفع. تعذر الحصول على معلومات الملف.", "Invalid directory." => "مسار غير صحيح.", "Files" => "الملفات", "Unable to upload {filename} as it is a directory or has 0 bytes" => "تعذر رفع الملف {filename} إما لأنه مجلد أو لان حجم الملف 0 بايت", -"Not enough space available" => "لا توجد مساحة كافية", "Upload cancelled." => "تم إلغاء عملية رفع الملفات .", "Could not get result from server." => "تعذر الحصول على نتيجة من الخادم", "File upload is in progress. Leaving the page now will cancel the upload." => "عملية رفع الملفات قيد التنفيذ. اغلاق الصفحة سوف يلغي عملية رفع الملفات.", @@ -27,28 +27,23 @@ $TRANSLATIONS = array( "Share" => "شارك", "Delete permanently" => "حذف بشكل دائم", "Rename" => "إعادة تسميه", -"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}", -"_Uploading %n file_::_Uploading %n files_" => array("لا يوجد ملفات %n لتحميلها","تحميل 1 ملف %n","تحميل 2 ملف %n","يتم تحميل عدد قليل من ملفات %n","يتم تحميل عدد كبير من ملفات %n","يتم تحميل ملفات %n"), -"'.' is an invalid file name." => "\".\" اسم ملف غير صحيح.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "اسم غير صحيح , الرموز '\\', '/', '<', '>', ':', '\"', '|', '?' و \"*\" غير مسموح استخدامها", -"Your storage is full, files can not be updated or synced anymore!" => "مساحتك التخزينية ممتلئة, لا يمكم تحديث ملفاتك أو مزامنتها بعد الآن !", -"Your storage is almost full ({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." => "جاري تجهيز عملية التحميل. قد تستغرق بعض الوقت اذا كان حجم الملفات كبير.", +"Pending" => "قيد الانتظار", "Error moving file" => "حدث خطأ أثناء نقل الملف", "Error" => "خطأ", "Name" => "اسم", "Size" => "حجم", "Modified" => "معدل", +"_%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"), +"_Uploading %n file_::_Uploading %n files_" => array("لا يوجد ملفات %n لتحميلها","تحميل 1 ملف %n","تحميل 2 ملف %n","يتم تحميل عدد قليل من ملفات %n","يتم تحميل عدد كبير من ملفات %n","يتم تحميل ملفات %n"), +"Your storage is full, files can not be updated or synced anymore!" => "مساحتك التخزينية ممتلئة, لا يمكم تحديث ملفاتك أو مزامنتها بعد الآن !", +"Your storage is almost full ({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." => "تم تعطيل التشفير لكن ملفاتك لا تزال مشفرة. فضلا اذهب إلى الإعدادات الشخصية لإزالة التشفير عن ملفاتك.", +"{dirs} and {files}" => "{dirs} و {files}", "%s could not be renamed" => "%s لا يمكن إعادة تسميته. ", -"Upload" => "رفع", "File handling" => "التعامل مع الملف", "Maximum upload size" => "الحد الأقصى لحجم الملفات التي يمكن رفعها", "max. possible: " => "الحد الأقصى المسموح به", @@ -59,6 +54,7 @@ $TRANSLATIONS = array( "Save" => "حفظ", "New" => "جديد", "Text file" => "ملف", +"New folder" => "مجلد جديد", "Folder" => "مجلد", "From link" => "من رابط", "Deleted files" => "حذف الملفات", @@ -69,7 +65,6 @@ $TRANSLATIONS = array( "Upload too large" => "حجم الترفيع أعلى من المسموح", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "حجم الملفات التي تريد ترفيعها أعلى من المسموح على الخادم.", "Files are being scanned, please wait." => "يرجى الانتظار , جاري فحص الملفات .", -"Current scanning" => "الفحص الحالي", -"Upgrading filesystem cache..." => "تحديث ذاكرة التخزين المؤقت(الكاش) الخاصة بملفات النظام ..." +"Current scanning" => "الفحص الحالي" ); $PLURAL_FORMS = "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"; diff --git a/apps/files/l10n/ast.php b/apps/files/l10n/ast.php new file mode 100644 index 0000000000..a2568ae763 --- /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", +"Name" => "Nome", +"Size" => "Tamañu", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), +"Save" => "Guardar", +"New folder" => "Nueva carpeta", +"Folder" => "Carpeta", +"Cancel upload" => "Encaboxar xuba", +"Download" => "Descargar", +"Delete" => "Desaniciar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/az.php b/apps/files/l10n/az.php index 70ab6572ba..0157af093e 100644 --- a/apps/files/l10n/az.php +++ b/apps/files/l10n/az.php @@ -1,7 +1,7 @@ array(""), -"_%n file_::_%n files_" => array(""), -"_Uploading %n file_::_Uploading %n files_" => array("") +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") ); -$PLURAL_FORMS = "nplurals=1; plural=0;"; +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/be.php b/apps/files/l10n/be.php index 830400b93f..f97fc27e2d 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 12e699064b..f9ef3750b5 100644 --- a/apps/files/l10n/bg_BG.php +++ b/apps/files/l10n/bg_BG.php @@ -13,15 +13,13 @@ $TRANSLATIONS = array( "Delete permanently" => "Изтриване завинаги", "Rename" => "Преименуване", "Pending" => "Чакащо", -"undo" => "възтановяване", -"_%n folder_::_%n folders_" => array("",""), -"_%n file_::_%n files_" => array("",""), -"_Uploading %n file_::_Uploading %n files_" => array("",""), "Error" => "Грешка", "Name" => "Име", "Size" => "Размер", "Modified" => "Променено", -"Upload" => "Качване", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "Maximum upload size" => "Максимален размер за качване", "0 is unlimited" => "Ползвайте 0 за без ограничения", "Save" => "Запис", diff --git a/apps/files/l10n/bn_BD.php b/apps/files/l10n/bn_BD.php index f7266517e9..b96d2515f1 100644 --- a/apps/files/l10n/bn_BD.php +++ b/apps/files/l10n/bn_BD.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "%s কে স্থানান্তর করা সম্ভব হলো না - এই নামের ফাইল বিদ্যমান", "Could not move %s" => "%s কে স্থানান্তর করা সম্ভব হলো না", "File name cannot be empty." => "ফাইলের নামটি ফাঁকা রাখা যাবে না।", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "নামটি সঠিক নয়, '\\', '/', '<', '>', ':', '\"', '|', '?' এবং '*' অনুমোদিত নয়।", "No file was uploaded. Unknown error" => "কোন ফাইল আপলোড করা হয় নি। সমস্যার কারণটি অজ্ঞাত।", "There is no error, the file uploaded with success" => "কোন সমস্যা হয় নি, ফাইল আপলোড সুসম্পন্ন হয়েছে।", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "আপলোড করা ফাইলটি php.ini তে বর্ণিত upload_max_filesize নির্দেশিত আয়তন অতিক্রম করছেঃ", @@ -13,25 +14,19 @@ $TRANSLATIONS = array( "Failed to write to disk" => "ডিস্কে লিখতে ব্যর্থ", "Invalid directory." => "ভুল ডিরেক্টরি", "Files" => "ফাইল", -"Not enough space available" => "যথেষ্ঠ পরিমাণ স্থান নেই", "Upload cancelled." => "আপলোড বাতিল করা হয়েছে।", "File upload is in progress. Leaving the page now will cancel the upload." => "ফাইল আপলোড চলমান। এই পৃষ্ঠা পরিত্যাগ করলে আপলোড বাতিল করা হবে।", "{new_name} already exists" => "{new_name} টি বিদ্যমান", "Share" => "ভাগাভাগি কর", "Rename" => "পূনঃনামকরণ", "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("",""), -"'.' is an invalid file name." => "টি একটি অননুমোদিত নাম।", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "নামটি সঠিক নয়, '\\', '/', '<', '>', ':', '\"', '|', '?' এবং '*' অনুমোদিত নয়।", "Error" => "সমস্যা", "Name" => "রাম", "Size" => "আকার", "Modified" => "পরিবর্তিত", -"Upload" => "আপলোড", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "File handling" => "ফাইল হ্যার্ডলিং", "Maximum upload size" => "আপলোডের সর্বোচ্চ আকার", "max. possible: " => "অনুমোদিত সর্বোচ্চ আকার", diff --git a/apps/files/l10n/bs.php b/apps/files/l10n/bs.php index 47276eccda..89ff91da03 100644 --- a/apps/files/l10n/bs.php +++ b/apps/files/l10n/bs.php @@ -1,11 +1,11 @@ "Podijeli", +"Name" => "Ime", +"Size" => "Veličina", "_%n folder_::_%n folders_" => array("","",""), "_%n file_::_%n files_" => array("","",""), "_Uploading %n file_::_Uploading %n files_" => array("","",""), -"Name" => "Ime", -"Size" => "Veličina", "Save" => "Spasi", "New folder" => "Nova fascikla", "Folder" => "Fasikla" diff --git a/apps/files/l10n/ca.php b/apps/files/l10n/ca.php index 261713bc58..6226168175 100644 --- a/apps/files/l10n/ca.php +++ b/apps/files/l10n/ca.php @@ -3,13 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "No s'ha pogut moure %s - Ja hi ha un fitxer amb aquest nom", "Could not move %s" => " No s'ha pogut moure %s", "File name cannot be empty." => "El nom del fitxer no pot ser buit.", -"File name must not contain \"/\". Please choose a different name." => "El nom de fitxer no pot contenir \"/\". Indiqueu un nom diferent.", +"\"%s\" is an invalid file name." => "\"%s\" no es un fitxer vàlid.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "El nóm no és vàlid, '\\', '/', '<', '>', ':', '\"', '|', '?' i '*' no estan permesos.", +"The target folder has been moved or deleted." => "La carpeta de destí s'ha mogut o eliminat.", "The name %s is already used in the folder %s. Please choose a different name." => "El nom %s ja s'usa en la carpeta %s. Indiqueu un nom diferent.", "Not a valid source" => "No és un origen vàlid", +"Server is not allowed to open URLs, please check the server configuration" => "El servidor no té autorització per obrir URLs, comproveu la configuració del servidor", "Error while downloading %s to %s" => "S'ha produït un error en baixar %s a %s", "Error when creating the file" => "S'ha produït un error en crear el fitxer", "Folder name cannot be empty." => "El nom de la carpeta no pot ser buit.", -"Folder name must not contain \"/\". Please choose a different name." => "El nom de la carpeta no pot contenir \"/\". Indiqueu un nom diferent.", "Error when creating the folder" => "S'ha produït un error en crear la carpeta", "Unable to set upload directory." => "No es pot establir la carpeta de pujada.", "Invalid Token" => "Testimoni no vàlid", @@ -22,48 +24,44 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Falta un fitxer temporal", "Failed to write to disk" => "Ha fallat en escriure al disc", "Not enough storage available" => "No hi ha prou espai disponible", -"Upload failed. Could not get file info." => "La pujada ha fallat. No s'ha pogut obtenir informació del fitxer.", "Upload failed. Could not find uploaded file" => "La pujada ha fallat. El fitxer pujat no s'ha trobat.", +"Upload failed. Could not get file info." => "La pujada ha fallat. No s'ha pogut obtenir informació del fitxer.", "Invalid directory." => "Directori no vàlid.", "Files" => "Fitxers", "Unable to upload {filename} as it is a directory or has 0 bytes" => "No es pot pujar {filename} perquè és una carpeta o té 0 bytes", -"Not enough space available" => "No hi ha prou espai disponible", +"Total file size {size1} exceeds upload limit {size2}" => "Mida total del fitxer {size1} excedeix el límit de pujada {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "No hi ha prou espai lliure, està carregant {size1} però només pot {size2}", "Upload cancelled." => "La pujada s'ha cancel·lat.", "Could not get result from server." => "No hi ha resposta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "Hi ha una pujada en curs. Si abandoneu la pàgina la pujada es cancel·larà.", "URL cannot be empty" => "L'URL no pot ser buit", -"In the home folder 'Shared' is a reserved filename" => "A la carpeta inici 'Compartit' és un nom de fitxer reservat", "{new_name} already exists" => "{new_name} ja existeix", "Could not create file" => "No s'ha pogut crear el fitxer", "Could not create folder" => "No s'ha pogut crear la carpeta", +"Error fetching URL" => "Error en obtenir la URL", "Share" => "Comparteix", "Delete permanently" => "Esborra permanentment", "Rename" => "Reanomena", +"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.", "Pending" => "Pendent", +"Error moving file" => "Error en moure el fitxer", +"Error" => "Error", "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.", +"Name" => "Nom", +"Size" => "Mida", +"Modified" => "Modificat", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetes"), "_%n file_::_%n files_" => array("%n fitxer","%n fitxers"), -"{dirs} and {files}" => "{dirs} i {files}", "_Uploading %n file_::_Uploading %n files_" => array("Pujant %n fitxer","Pujant %n fitxers"), -"'.' is an invalid file name." => "'.' és un nom no vàlid per un fitxer.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "El nóm no és vàlid, '\\', '/', '<', '>', ':', '\"', '|', '?' i '*' no estan permesos.", +"\"{name}\" is an invalid file name." => "\"{name}\" no es un fitxer vàlid.", "Your storage is full, files can not be updated or synced anymore!" => "El vostre espai d'emmagatzemament és ple, els fitxers ja no es poden actualitzar o sincronitzar!", "Your storage is almost full ({usedSpacePercent}%)" => "El vostre espai d'emmagatzemament és gairebé ple ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "L'aplicació d'encriptació està activada però les claus no estan inicialitzades, sortiu i acrediteu-vos de nou.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nom de carpeta no vàlid. L'ús de 'Shared' és reservat", +"{dirs} and {files}" => "{dirs} i {files}", "%s could not be renamed" => "%s no es pot canviar el nom", -"Upload" => "Puja", "File handling" => "Gestió de fitxers", "Maximum upload size" => "Mida màxima de pujada", "max. possible: " => "màxim possible:", @@ -87,7 +85,6 @@ $TRANSLATIONS = array( "Upload too large" => "La pujada és massa gran", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Els fitxers que esteu intentant pujar excedeixen la mida màxima de pujada del servidor", "Files are being scanned, please wait." => "S'estan escanejant els fitxers, espereu", -"Current scanning" => "Actualment escanejant", -"Upgrading filesystem cache..." => "Actualitzant la memòria de cau del sistema de fitxers..." +"Current scanning" => "Actualment escanejant" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/cs_CZ.php b/apps/files/l10n/cs_CZ.php index 44e0fdae1f..8fa0bb2137 100644 --- a/apps/files/l10n/cs_CZ.php +++ b/apps/files/l10n/cs_CZ.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Nelze přesunout %s - již existuje soubor se stejným názvem", "Could not move %s" => "Nelze přesunout %s", "File name cannot be empty." => "Název souboru nemůže být prázdný řetězec.", -"File name must not contain \"/\". Please choose a different name." => "Název souboru nesmí obsahovat \"/\". Vyberte prosím jiné jméno.", +"\"%s\" is an invalid file name." => "\"%s\" je neplatným názvem souboru.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neplatný název, znaky '\\', '/', '<', '>', ':', '\"', '|', '?' a '*' nejsou povoleny.", +"The target folder has been moved or deleted." => "Cílová složka byla přesunuta nebo smazána.", "The name %s is already used in the folder %s. Please choose a different name." => "Název %s ve složce %s již existuje. Vyberte prosím jiné jméno.", "Not a valid source" => "Neplatný zdroj", "Server is not allowed to open URLs, please check the server configuration" => "Server není oprávněn otevírat adresy URL. Ověřte, prosím, konfiguraci serveru.", "Error while downloading %s to %s" => "Chyba při stahování %s do %s", "Error when creating the file" => "Chyba při vytváření souboru", "Folder name cannot be empty." => "Název složky nemůže být prázdný.", -"Folder name must not contain \"/\". Please choose a different name." => "Název složky nesmí obsahovat \"/\". Zvolte prosím jiný.", "Error when creating the folder" => "Chyba při vytváření složky", "Unable to set upload directory." => "Nelze nastavit adresář pro nahrané soubory.", "Invalid Token" => "Neplatný token", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Chybí adresář pro dočasné soubory", "Failed to write to disk" => "Zápis na disk selhal", "Not enough storage available" => "Nedostatek dostupného úložného prostoru", -"Upload failed. Could not get file info." => "Nahrávání selhalo. Nepodařilo se získat informace o souboru.", "Upload failed. Could not find uploaded file" => "Nahrávání selhalo. Nepodařilo se nalézt nahraný soubor.", +"Upload failed. Could not get file info." => "Nahrávání selhalo. Nepodařilo se získat informace o souboru.", "Invalid directory." => "Neplatný adresář", "Files" => "Soubory", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Nelze nahrát soubor {filename}, protože je to buď adresář nebo má velikost 0 bytů", -"Not enough space available" => "Nedostatek volného místa", +"Total file size {size1} exceeds upload limit {size2}" => "Celková velikost souboru {size1} překračuje povolenou velikost pro nahrávání {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Není dostatek místa pro uložení, velikost souboru je {size1}, zbývá pouze {size2}", "Upload cancelled." => "Odesílání zrušeno.", "Could not get result from server." => "Nepodařilo se získat výsledek ze serveru.", "File upload is in progress. Leaving the page now will cancel the upload." => "Probíhá odesílání souboru. Opuštění stránky způsobí zrušení nahrávání.", "URL cannot be empty" => "URL nemůže zůstat prázdná", -"In the home folder 'Shared' is a reserved filename" => "V osobní složce je název 'Shared' rezervovaný", "{new_name} already exists" => "{new_name} již existuje", "Could not create file" => "Nepodařilo se vytvořit soubor", "Could not create folder" => "Nepodařilo se vytvořit složku", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Sdílet", "Delete permanently" => "Trvale odstranit", "Rename" => "Přejmenovat", +"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.", "Pending" => "Nevyřízené", +"Error moving file." => "Chyba při přesunu souboru.", +"Error moving file" => "Chyba při přesunu souboru", +"Error" => "Chyba", "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.", +"Name" => "Název", +"Size" => "Velikost", +"Modified" => "Upraveno", "_%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ů"), -"{dirs} and {files}" => "{dirs} a {files}", "_Uploading %n file_::_Uploading %n files_" => array("Nahrávám %n soubor","Nahrávám %n soubory","Nahrávám %n souborů"), -"'.' is an invalid file name." => "'.' je neplatným názvem souboru.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neplatný název, znaky '\\', '/', '<', '>', ':', '\"', '|', '?' a '*' nejsou povoleny.", +"\"{name}\" is an invalid file name." => "\"{name}\" je neplatným názvem souboru.", "Your storage is full, files can not be updated or synced anymore!" => "Vaše úložiště je plné, nelze aktualizovat ani synchronizovat soubory.", "Your storage is almost full ({usedSpacePercent}%)" => "Vaše úložiště je téměř plné ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Aplikace pro šifrování je zapnuta, ale vaše klíče nejsou inicializované. Prosím odhlaste se a znovu přihlaste", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Neplatný název složky. Použití 'Shared' je rezervováno.", +"{dirs} and {files}" => "{dirs} a {files}", "%s could not be renamed" => "%s nemůže být přejmenován", -"Upload" => "Odeslat", +"Upload (max. %s)" => "Nahrát (max. %s)", "File handling" => "Zacházení se soubory", "Maximum upload size" => "Maximální velikost pro odesílání", "max. possible: " => "největší možná: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Odesílaný soubor je příliš velký", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Soubory, které se snažíte odeslat, překračují limit velikosti odesílání na tomto serveru.", "Files are being scanned, please wait." => "Soubory se prohledávají, prosím čekejte.", -"Current scanning" => "Aktuální prohledávání", -"Upgrading filesystem cache..." => "Aktualizuji mezipaměť souborového systému..." +"Current scanning" => "Aktuální prohledávání" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/apps/files/l10n/cy_GB.php b/apps/files/l10n/cy_GB.php index 2a007761c5..6ed94e5c77 100644 --- a/apps/files/l10n/cy_GB.php +++ b/apps/files/l10n/cy_GB.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Methwyd symud %s - Mae ffeil gyda'r enw hwn eisoes yn bodoli", "Could not move %s" => "Methwyd symud %s", "File name cannot be empty." => "Does dim hawl cael enw ffeil gwag.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Enw annilys, ni chaniateir, '\\', '/', '<', '>', ':', '\"', '|', '?' na '*'.", "No file was uploaded. Unknown error" => "Ni lwythwyd ffeil i fyny. Gwall anhysbys.", "There is no error, the file uploaded with success" => "Does dim gwall, llwythodd y ffeil i fyny'n llwyddiannus", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Mae'r ffeil lwythwyd i fyny'n fwy na chyfarwyddeb upload_max_filesize yn php.ini:", @@ -14,29 +15,23 @@ $TRANSLATIONS = array( "Not enough storage available" => "Dim digon o le storio ar gael", "Invalid directory." => "Cyfeiriadur annilys.", "Files" => "Ffeiliau", -"Not enough space available" => "Dim digon o le ar gael", "Upload cancelled." => "Diddymwyd llwytho i fyny.", "File upload is in progress. Leaving the page now will cancel the upload." => "Mae ffeiliau'n cael eu llwytho i fyny. Bydd gadael y dudalen hon nawr yn diddymu'r broses.", "{new_name} already exists" => "{new_name} yn bodoli'n barod", "Share" => "Rhannu", "Delete permanently" => "Dileu'n barhaol", "Rename" => "Ailenwi", -"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("","","",""), -"'.' is an invalid file name." => "Mae '.' yn enw ffeil annilys.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Enw annilys, ni chaniateir, '\\', '/', '<', '>', ':', '\"', '|', '?' na '*'.", -"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.", +"Pending" => "I ddod", "Error" => "Gwall", "Name" => "Enw", "Size" => "Maint", "Modified" => "Addaswyd", -"Upload" => "Llwytho i fyny", +"_%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}%)", "File handling" => "Trafod ffeiliau", "Maximum upload size" => "Maint mwyaf llwytho i fyny", "max. possible: " => "mwyaf. posib:", @@ -57,7 +52,6 @@ $TRANSLATIONS = array( "Upload too large" => "Maint llwytho i fyny'n rhy fawr", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Mae'r ffeiliau rydych yn ceisio llwytho i fyny'n fwy na maint mwyaf llwytho ffeiliau i fyny ar y gweinydd hwn.", "Files are being scanned, please wait." => "Arhoswch, mae ffeiliau'n cael eu sganio.", -"Current scanning" => "Sganio cyfredol", -"Upgrading filesystem cache..." => "Uwchraddio storfa system ffeiliau..." +"Current scanning" => "Sganio cyfredol" ); $PLURAL_FORMS = "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"; diff --git a/apps/files/l10n/da.php b/apps/files/l10n/da.php index 9b7722444a..076fa46b4c 100644 --- a/apps/files/l10n/da.php +++ b/apps/files/l10n/da.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Kunne ikke flytte %s - der findes allerede en fil med dette navn", "Could not move %s" => "Kunne ikke flytte %s", "File name cannot be empty." => "Filnavnet kan ikke stå tomt.", -"File name must not contain \"/\". Please choose a different name." => "Filnavnet må ikke indeholde \"/\". Vælg venligst et andet navn.", +"\"%s\" is an invalid file name." => "\"%s\" er et ugyldigt filnavn.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldigt navn, '\\', '/', '<', '>', ':' | '?', '\"', '', og '*' er ikke tilladt.", +"The target folder has been moved or deleted." => "Mappen er blevet slettet eller fjernet.", "The name %s is already used in the folder %s. Please choose a different name." => "Navnet %s er allerede i brug i mappen %s. Vælg venligst et andet navn.", "Not a valid source" => "Ikke en gyldig kilde", "Server is not allowed to open URLs, please check the server configuration" => "Server har ikke tilladelse til at åbne URL'er. Kontroller venligst serverens indstillinger", "Error while downloading %s to %s" => "Fejl ved hentning af %s til %s", "Error when creating the file" => "Fejl ved oprettelse af fil", "Folder name cannot be empty." => "Mappenavnet kan ikke være tomt.", -"Folder name must not contain \"/\". Please choose a different name." => "Mappenavnet må ikke indeholde \"/\". Vælg venligst et andet navn.", "Error when creating the folder" => "Fejl ved oprettelse af mappen", "Unable to set upload directory." => "Ude af stand til at vælge upload mappe.", "Invalid Token" => "Ugyldig Token ", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Manglende midlertidig mappe.", "Failed to write to disk" => "Fejl ved skrivning til disk.", "Not enough storage available" => "Der er ikke nok plads til rådlighed", -"Upload failed. Could not get file info." => "Upload fejlede. Kunne ikke hente filinformation.", "Upload failed. Could not find uploaded file" => "Upload fejlede. Kunne ikke finde den uploadede fil.", +"Upload failed. Could not get file info." => "Upload fejlede. Kunne ikke hente filinformation.", "Invalid directory." => "Ugyldig mappe.", "Files" => "Filer", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Kan ikke upload {filename} da det er enten en mappe eller indholder 0 bytes.", -"Not enough space available" => "ikke nok tilgængelig ledig plads ", +"Total file size {size1} exceeds upload limit {size2}" => "Den totale filstørrelse {size1} er større end uploadgrænsen {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Der er ikke tilstrækkeligt friplads. Du uplaoder {size1} men der er kun {size2} tilbage", "Upload cancelled." => "Upload afbrudt.", "Could not get result from server." => "Kunne ikke hente resultat fra server.", "File upload is in progress. Leaving the page now will cancel the upload." => "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret.", "URL cannot be empty" => "URL kan ikke være tom", -"In the home folder 'Shared' is a reserved filename" => "Navnet 'Shared' er reserveret i hjemmemappen.", "{new_name} already exists" => "{new_name} eksisterer allerede", "Could not create file" => "Kunne ikke oprette fil", "Could not create folder" => "Kunne ikke oprette mappe", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Del", "Delete permanently" => "Slet permanent", "Rename" => "Omdøb", +"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.", "Pending" => "Afventer", +"Error moving file." => "Fejl ved flytning af fil", +"Error moving file" => "Fejl ved flytning af fil", +"Error" => "Fejl", "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.", +"Name" => "Navn", +"Size" => "Størrelse", +"Modified" => "Ændret", "_%n folder_::_%n folders_" => array("%n mappe","%n mapper"), "_%n file_::_%n files_" => array("%n fil","%n filer"), -"{dirs} and {files}" => "{dirs} og {files}", "_Uploading %n file_::_Uploading %n files_" => array("Uploader %n fil","Uploader %n filer"), -"'.' is an invalid file name." => "'.' er et ugyldigt filnavn.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldigt navn, '\\', '/', '<', '>', ':' | '?', '\"', '', og '*' er ikke tilladt.", +"\"{name}\" is an invalid file name." => "'{name}' er et ugyldigt filnavn.", "Your storage is full, files can not be updated or synced anymore!" => "Din opbevaringsplads er fyldt op, filer kan ikke opdateres eller synkroniseres længere!", "Your storage is almost full ({usedSpacePercent}%)" => "Din opbevaringsplads er næsten fyldt op ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Krypteringsprogrammet er aktiveret, men din nøgle er ikke igangsat. Log venligst ud og ind igen.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Ugyldig mappenavn. 'Shared' er reserveret.", +"{dirs} and {files}" => "{dirs} og {files}", "%s could not be renamed" => "%s kunne ikke omdøbes", -"Upload" => "Upload", +"Upload (max. %s)" => "Upload (max. %s)", "File handling" => "Filhåndtering", "Maximum upload size" => "Maksimal upload-størrelse", "max. possible: " => "max. mulige: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Upload er for stor", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filerne, du prøver at uploade, er større end den maksimale størrelse for fil-upload på denne server.", "Files are being scanned, please wait." => "Filerne bliver indlæst, vent venligst.", -"Current scanning" => "Indlæser", -"Upgrading filesystem cache..." => "Opgraderer filsystems cachen..." +"Current scanning" => "Indlæser" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/de.php b/apps/files/l10n/de.php index b209fee88a..8ad0f8909f 100644 --- a/apps/files/l10n/de.php +++ b/apps/files/l10n/de.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Konnte %s nicht verschieben. Eine Datei mit diesem Namen existiert bereits", "Could not move %s" => "Konnte %s nicht verschieben", "File name cannot be empty." => "Der Dateiname darf nicht leer sein.", -"File name must not contain \"/\". Please choose a different name." => "Der Dateiname darf kein \"/\" enthalten. Bitte wähle einen anderen Namen.", +"\"%s\" is an invalid file name." => "\"%s\" ist kein gültiger Dateiname.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.", +"The target folder has been moved or deleted." => "Der Zielordner wurde verschoben oder gelöscht.", "The name %s is already used in the folder %s. Please choose a different name." => "Der Name %s wird bereits im Ordner %s benutzt. Bitte wähle einen anderen Namen.", "Not a valid source" => "Keine gültige Quelle", "Server is not allowed to open URLs, please check the server configuration" => "Dem Server ist das Öffnen von URLs nicht erlaubt, bitte die Serverkonfiguration prüfen", "Error while downloading %s to %s" => "Fehler beim Herunterladen von %s nach %s", "Error when creating the file" => "Fehler beim Erstellen der Datei", "Folder name cannot be empty." => "Der Ordner-Name darf nicht leer sein.", -"Folder name must not contain \"/\". Please choose a different name." => "Der Ordner-Name darf kein \"/\" enthalten. Bitte wähle einen anderen Namen.", "Error when creating the folder" => "Fehler beim Erstellen des Ordners", "Unable to set upload directory." => "Das Upload-Verzeichnis konnte nicht gesetzt werden.", "Invalid Token" => "Ungültiges Merkmal", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Kein temporärer Ordner vorhanden", "Failed to write to disk" => "Fehler beim Schreiben auf die Festplatte", "Not enough storage available" => "Nicht genug Speicher vorhanden.", -"Upload failed. Could not get file info." => "Hochladen fehlgeschlagen. Dateiinformationen konnten nicht abgerufen werden.", "Upload failed. Could not find uploaded file" => "Hochladen fehlgeschlagen. Hochgeladene Datei konnte nicht gefunden werden.", +"Upload failed. Could not get file info." => "Hochladen fehlgeschlagen. Dateiinformationen konnten nicht abgerufen werden.", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist", -"Not enough space available" => "Nicht genug Speicherplatz verfügbar", +"Total file size {size1} exceeds upload limit {size2}" => "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Nicht genügend freier Speicherplatz, du möchtest {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.", "Upload cancelled." => "Upload abgebrochen.", "Could not get result from server." => "Ergebnis konnte nicht vom Server abgerufen werden.", "File upload is in progress. Leaving the page now will cancel the upload." => "Dateiupload läuft. Wenn Du die Seite jetzt verlässt, wird der Upload abgebrochen.", "URL cannot be empty" => "Die URL darf nicht leer sein", -"In the home folder 'Shared' is a reserved filename" => "Das Benutzerverzeichnis 'Shared' ist ein reservierter Dateiname", "{new_name} already exists" => "{new_name} existiert bereits", "Could not create file" => "Die Datei konnte nicht erstellt werden", "Could not create folder" => "Der Ordner konnte nicht erstellt werden", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Teilen", "Delete permanently" => "Endgültig löschen", "Rename" => "Umbenennen", +"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.", "Pending" => "Ausstehend", +"Error moving file." => "Fehler beim Verschieben der Datei.", +"Error moving file" => "Fehler beim Verschieben der Datei", +"Error" => "Fehler", "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.", +"Name" => "Name", +"Size" => "Größe", +"Modified" => "Geändert", "_%n folder_::_%n folders_" => array("%n Ordner","%n Ordner"), "_%n file_::_%n files_" => array("%n Datei","%n Dateien"), -"{dirs} and {files}" => "{dirs} und {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n Datei wird hochgeladen","%n Dateien werden hochgeladen"), -"'.' is an invalid file name." => "'.' ist kein gültiger Dateiname.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.", +"\"{name}\" is an invalid file name." => "\"{name}\" ist kein gültiger Dateiname.", "Your storage is full, files can not be updated or synced anymore!" => "Dein Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!", "Your storage is almost full ({usedSpacePercent}%)" => "Dein Speicher ist fast voll ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Die Verschlüsselung-App ist aktiviert, aber Deine Schlüssel sind nicht initialisiert. Bitte melden Dich nochmals ab und wieder an.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Ungültiger Verzeichnisname. Die Nutzung von 'Shared' ist reserviert.", +"{dirs} and {files}" => "{dirs} und {files}", "%s could not be renamed" => "%s konnte nicht umbenannt werden", -"Upload" => "Hochladen", +"Upload (max. %s)" => "Hochladen (max. %s)", "File handling" => "Dateibehandlung", "Maximum upload size" => "Maximale Upload-Größe", "max. possible: " => "maximal möglich:", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Der Upload ist zu groß", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server.", "Files are being scanned, please wait." => "Dateien werden gescannt, bitte warten.", -"Current scanning" => "Scanne", -"Upgrading filesystem cache..." => "Dateisystem-Cache wird aktualisiert ..." +"Current scanning" => "Scanne" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/de_AT.php b/apps/files/l10n/de_AT.php index 0157af093e..e1b55f6dd1 100644 --- a/apps/files/l10n/de_AT.php +++ b/apps/files/l10n/de_AT.php @@ -1,7 +1,11 @@ "Freigeben", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), -"_Uploading %n file_::_Uploading %n files_" => array("","") +"_Uploading %n file_::_Uploading %n files_" => array("",""), +"Save" => "Speichern", +"Download" => "Herunterladen", +"Delete" => "Löschen" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/de_CH.php b/apps/files/l10n/de_CH.php index b950429346..625b9387b0 100644 --- a/apps/files/l10n/de_CH.php +++ b/apps/files/l10n/de_CH.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "%s konnte nicht verschoben werden. Eine Datei mit diesem Namen existiert bereits.", "Could not move %s" => "Konnte %s nicht verschieben", "File name cannot be empty." => "Der Dateiname darf nicht leer sein.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, «\\», «/», «<», «>», «:», «\"», «|», «?» und «*» sind nicht zulässig.", "Unable to set upload directory." => "Das Upload-Verzeichnis konnte nicht gesetzt werden.", "Invalid Token" => "Ungültiges Merkmal", "No file was uploaded. Unknown error" => "Keine Datei hochgeladen. Unbekannter Fehler", @@ -16,31 +17,25 @@ $TRANSLATIONS = array( "Not enough storage available" => "Nicht genug Speicher vorhanden.", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", -"Not enough space available" => "Nicht genügend Speicherplatz verfügbar", "Upload cancelled." => "Upload abgebrochen.", "File upload is in progress. Leaving the page now will cancel the upload." => "Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen.", "{new_name} already exists" => "{new_name} existiert bereits", "Share" => "Teilen", "Delete permanently" => "Endgültig löschen", "Rename" => "Umbenennen", -"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"), -"'.' is an invalid file name." => "'.' ist kein gültiger Dateiname.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, «\\», «/», «<», «>», «:», «\"», «|», «?» und «*» sind nicht zulässig.", -"Your storage is full, files can not be updated or synced anymore!" => "Ihr Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!", -"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.", +"Pending" => "Ausstehend", "Error" => "Fehler", "Name" => "Name", "Size" => "Grösse", "Modified" => "Geändert", +"_%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"), +"Your storage is full, files can not be updated or synced anymore!" => "Ihr Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!", +"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.", "%s could not be renamed" => "%s konnte nicht umbenannt werden", -"Upload" => "Hochladen", "File handling" => "Dateibehandlung", "Maximum upload size" => "Maximale Upload-Grösse", "max. possible: " => "maximal möglich:", @@ -62,7 +57,6 @@ $TRANSLATIONS = array( "Upload too large" => "Der Upload ist zu gross", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Die Datei überschreitet die Maximalgrösse für Uploads auf diesem Server.", "Files are being scanned, please wait." => "Dateien werden gescannt, bitte warten.", -"Current scanning" => "Scanne", -"Upgrading filesystem cache..." => "Dateisystem-Cache wird aktualisiert ..." +"Current scanning" => "Scanne" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/de_DE.php b/apps/files/l10n/de_DE.php index 76cdce00e4..9a834f1cc3 100644 --- a/apps/files/l10n/de_DE.php +++ b/apps/files/l10n/de_DE.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "%s konnte nicht verschoben werden. Eine Datei mit diesem Namen existiert bereits.", "Could not move %s" => "Konnte %s nicht verschieben", "File name cannot be empty." => "Der Dateiname darf nicht leer sein.", -"File name must not contain \"/\". Please choose a different name." => "Der Dateiname darf kein \"/\" enthalten. Bitte wählen Sie einen anderen Namen.", +"\"%s\" is an invalid file name." => "\"%s\" ist kein gültiger Dateiname.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.", +"The target folder has been moved or deleted." => "Der Ziel-Ordner wurde verschoben oder gelöscht.", "The name %s is already used in the folder %s. Please choose a different name." => "Der Name %s wird bereits im Ordner %s benutzt. Bitte wählen Sie einen anderen Namen.", "Not a valid source" => "Keine gültige Quelle", "Server is not allowed to open URLs, please check the server configuration" => "Dem Server ist das Öffnen von URLs nicht erlaubt, bitte die Serverkonfiguration prüfen", "Error while downloading %s to %s" => "Fehler beim Herunterladen von %s nach %s", "Error when creating the file" => "Fehler beim Erstellen der Datei", "Folder name cannot be empty." => "Der Ordner-Name darf nicht leer sein.", -"Folder name must not contain \"/\". Please choose a different name." => "Der Ordner-Name darf kein \"/\" enthalten. Bitte wählen Sie einen anderen Namen.", "Error when creating the folder" => "Fehler beim Erstellen des Ordners", "Unable to set upload directory." => "Das Upload-Verzeichnis konnte nicht gesetzt werden.", "Invalid Token" => "Ungültiges Merkmal", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Kein temporärer Ordner vorhanden", "Failed to write to disk" => "Fehler beim Schreiben auf die Festplatte", "Not enough storage available" => "Nicht genug Speicher vorhanden.", -"Upload failed. Could not get file info." => "Hochladen fehlgeschlagen. Die Dateiinformationen konnten nicht abgerufen werden.", "Upload failed. Could not find uploaded file" => "Hochladen fehlgeschlagen. Die hochgeladene Datei konnte nicht gefunden werden.", +"Upload failed. Could not get file info." => "Hochladen fehlgeschlagen. Die Dateiinformationen konnten nicht abgerufen werden.", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Die Datei {filename} kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist", -"Not enough space available" => "Nicht genügend Speicherplatz verfügbar", +"Total file size {size1} exceeds upload limit {size2}" => "Die Gesamt-Größe {size1} überschreitet die Upload-Begrenzung {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Nicht genügend freier Speicherplatz, Sie möchten {size1} hochladen, es sind jedoch nur noch {size2} verfügbar.", "Upload cancelled." => "Upload abgebrochen.", "Could not get result from server." => "Ergebnis konnte nicht vom Server abgerufen werden.", "File upload is in progress. Leaving the page now will cancel the upload." => "Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen.", "URL cannot be empty" => "Die URL darf nicht leer sein", -"In the home folder 'Shared' is a reserved filename" => "Das Benutzerverzeichnis 'Shared' ist ein reservierter Dateiname", "{new_name} already exists" => "{new_name} existiert bereits", "Could not create file" => "Die Datei konnte nicht erstellt werden", "Could not create folder" => "Der Ordner konnte nicht erstellt werden", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Teilen", "Delete permanently" => "Endgültig löschen", "Rename" => "Umbenennen", +"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.", "Pending" => "Ausstehend", +"Error moving file." => "Fehler beim Verschieben der Datei.", +"Error moving file" => "Fehler beim Verschieben der Datei", +"Error" => "Fehler", "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.", +"Name" => "Name", +"Size" => "Größe", +"Modified" => "Geändert", "_%n folder_::_%n folders_" => array("%n Ordner","%n Ordner"), "_%n file_::_%n files_" => array("%n Datei","%n Dateien"), -"{dirs} and {files}" => "{dirs} und {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n Datei wird hoch geladen","%n Dateien werden hoch geladen"), -"'.' is an invalid file name." => "'.' ist kein gültiger Dateiname.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.", +"\"{name}\" is an invalid file name." => "\"{name}\" ist kein gültiger Dateiname.", "Your storage is full, files can not be updated or synced anymore!" => "Ihr Speicher ist voll, daher können keine Dateien mehr aktualisiert oder synchronisiert werden!", "Your storage is almost full ({usedSpacePercent}%)" => "Ihr Speicher ist fast voll ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Verschlüsselung-App ist aktiviert, aber Ihre Schlüssel sind nicht initialisiert. Bitte melden sich nochmals ab und wieder an.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Ungültiger Verzeichnisname. Die Nutzung von 'Shared' ist reserviert.", +"{dirs} and {files}" => "{dirs} und {files}", "%s could not be renamed" => "%s konnte nicht umbenannt werden", -"Upload" => "Hochladen", +"Upload (max. %s)" => "Hochladen (max. %s)", "File handling" => "Dateibehandlung", "Maximum upload size" => "Maximale Upload-Größe", "max. possible: " => "maximal möglich:", @@ -77,7 +75,7 @@ $TRANSLATIONS = array( "New" => "Neu", "New text file" => "Neue Textdatei", "Text file" => "Textdatei", -"New folder" => "Neues Verzeichnis", +"New folder" => "Neuer Ordner", "Folder" => "Ordner", "From link" => "Von einem Link", "Deleted files" => "Gelöschte Dateien", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Der Upload ist zu groß", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server.", "Files are being scanned, please wait." => "Dateien werden gescannt, bitte warten.", -"Current scanning" => "Scanne", -"Upgrading filesystem cache..." => "Dateisystem-Cache wird aktualisiert ..." +"Current scanning" => "Scanne" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/el.php b/apps/files/l10n/el.php index 9efe1af7dd..5ba92033d1 100644 --- a/apps/files/l10n/el.php +++ b/apps/files/l10n/el.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Αδυναμία μετακίνησης του %s - υπάρχει ήδη αρχείο με αυτό το όνομα", "Could not move %s" => "Αδυναμία μετακίνησης του %s", "File name cannot be empty." => "Το όνομα αρχείου δεν μπορεί να είναι κενό.", -"File name must not contain \"/\". Please choose a different name." => "Το όνομα αρχείου δεν μπορεί να περιέχει \"/\". Παρακαλώ επιλέξτε ένα διαφορετικό όνομα. ", +"\"%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, παρακαλώ ελέγξτε τις ρυθμίσεις του διακομιστή", "Error while downloading %s to %s" => "Σφάλμα κατά τη λήψη του %s στο %s", "Error when creating the file" => "Σφάλμα κατά τη δημιουργία του αρχείου", "Folder name cannot be empty." => "Το όνομα φακέλου δεν μπορεί να είναι κενό.", -"Folder name must not contain \"/\". Please choose a different name." => "Το όνομα φακέλου δεν μπορεί να περιέχει \"/\". Παρακαλώ επιλέξτε ένα διαφορετικό όνομα. ", "Error when creating the folder" => "Σφάλμα δημιουργίας φακέλου", "Unable to set upload directory." => "Αδυναμία ορισμού καταλόγου αποστολής.", "Invalid Token" => "Μη έγκυρο Token", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Λείπει ο προσωρινός φάκελος", "Failed to write to disk" => "Αποτυχία εγγραφής στο δίσκο", "Not enough storage available" => "Μη επαρκής διαθέσιμος αποθηκευτικός χώρος", -"Upload failed. Could not get file info." => "Η φόρτωση απέτυχε. Αδυναμία λήψης πληροφοριών αρχείων.", "Upload failed. Could not find uploaded file" => "Η φόρτωση απέτυχε. Αδυναμία εύρεσης αρχείου προς φόρτωση.", +"Upload failed. Could not get file info." => "Η φόρτωση απέτυχε. Αδυναμία λήψης πληροφοριών αρχείων.", "Invalid directory." => "Μη έγκυρος φάκελος.", "Files" => "Αρχεία", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Αδυναμία φόρτωσης {filename} καθώς είναι κατάλογος αρχείων ή έχει 0 bytes", -"Not enough space available" => "Δεν υπάρχει αρκετός διαθέσιμος χώρος", +"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." => "Η αποστολή του αρχείου βρίσκεται σε εξέλιξη. Το κλείσιμο της σελίδας θα ακυρώσει την αποστολή.", "URL cannot be empty" => "Η URL δεν πρέπει να είναι κενή", -"In the home folder 'Shared' is a reserved filename" => "Στον αρχικό φάκελο το όνομα 'Shared' διατηρείται από το σύστημα", "{new_name} already exists" => "{new_name} υπάρχει ήδη", "Could not create file" => "Αδυναμία δημιουργίας αρχείου", "Could not create folder" => "Αδυναμία δημιουργίας φακέλου", @@ -41,36 +42,32 @@ $TRANSLATIONS = array( "Share" => "Διαμοιρασμός", "Delete permanently" => "Μόνιμη διαγραφή", "Rename" => "Μετονομασία", +"Your download is being prepared. This might take some time if the files are big." => "Η λήψη προετοιμάζεται. Αυτό μπορεί να πάρει ώρα εάν τα αρχεία έχουν μεγάλο μέγεθος.", "Pending" => "Εκκρεμεί", +"Error moving file" => "Σφάλμα κατά τη μετακίνηση του αρχείου", +"Error" => "Σφάλμα", "Could not rename file" => "Αδυναμία μετονομασίας αρχείου", -"replaced {new_name} with {old_name}" => "αντικαταστάθηκε το {new_name} με {old_name}", -"undo" => "αναίρεση", "Error deleting file." => "Σφάλμα διαγραφής αρχείου.", +"Name" => "Όνομα", +"Size" => "Μέγεθος", +"Modified" => "Τροποποιήθηκε", "_%n folder_::_%n folders_" => array("%n φάκελος","%n φάκελοι"), "_%n file_::_%n files_" => array("%n αρχείο","%n αρχεία"), -"{dirs} and {files}" => "{Κατάλογοι αρχείων} και {αρχεία}", "_Uploading %n file_::_Uploading %n files_" => array("Ανέβασμα %n αρχείου","Ανέβασμα %n αρχείων"), -"'.' is an invalid file name." => "'.' είναι μη έγκυρο όνομα αρχείου.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Μη έγκυρο όνομα, '\\', '/', '<', '>', ':', '\"', '|', '?' και '*' δεν επιτρέπονται.", +"\"{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" => "Τροποποιήθηκε", -"Invalid folder name. Usage of 'Shared' is reserved." => "Άκυρο όνομα φακέλου. Η χρήση του 'Shared' διατηρείται από το σύστημα.", +"{dirs} and {files}" => "{Κατάλογοι αρχείων} και {αρχεία}", "%s could not be renamed" => "Αδυναμία μετονομασίας του %s", -"Upload" => "Μεταφόρτωση", +"Upload (max. %s)" => "Διαμοιρασμός (max. %s)", "File handling" => "Διαχείριση αρχείων", "Maximum upload size" => "Μέγιστο μέγεθος αποστολής", "max. possible: " => "μέγιστο δυνατό:", "Needed for multi-file and folder downloads." => "Απαραίτητο για κατέβασμα πολλαπλών αρχείων και φακέλων", -"Enable ZIP-download" => "Ενεργοποίηση κατεβάσματος ZIP", +"Enable ZIP-download" => "Επιτρέπεται η λήψη ZIP", "0 is unlimited" => "0 για απεριόριστο", "Maximum input size for ZIP files" => "Μέγιστο μέγεθος για αρχεία ZIP", "Save" => "Αποθήκευση", @@ -89,7 +86,6 @@ $TRANSLATIONS = array( "Upload too large" => "Πολύ μεγάλο αρχείο προς αποστολή", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Τα αρχεία που προσπαθείτε να ανεβάσετε υπερβαίνουν το μέγιστο μέγεθος αποστολής αρχείων σε αυτόν τον διακομιστή.", "Files are being scanned, please wait." => "Τα αρχεία σαρώνονται, παρακαλώ περιμένετε.", -"Current scanning" => "Τρέχουσα ανίχνευση", -"Upgrading filesystem cache..." => "Ενημέρωση της μνήμης cache του συστήματος αρχείων..." +"Current scanning" => "Τρέχουσα ανίχνευση" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/en_GB.php b/apps/files/l10n/en_GB.php index ac93aa68ab..5ebc141b80 100644 --- a/apps/files/l10n/en_GB.php +++ b/apps/files/l10n/en_GB.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Could not move %s - File with this name already exists", "Could not move %s" => "Could not move %s", "File name cannot be empty." => "File name cannot be empty.", -"File name must not contain \"/\". Please choose a different name." => "File name must not contain \"/\". Please choose a different name.", +"\"%s\" is an invalid file name." => "\"%s\" is an invalid file name.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Invalid name: '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.", +"The target folder has been moved or deleted." => "The target folder has been moved or deleted.", "The name %s is already used in the folder %s. Please choose a different name." => "The name %s is already used in the folder %s. Please choose a different name.", "Not a valid source" => "Not a valid source", "Server is not allowed to open URLs, please check the server configuration" => "Server is not allowed to open URLs, please check the server configuration", "Error while downloading %s to %s" => "Error whilst downloading %s to %s", "Error when creating the file" => "Error when creating the file", "Folder name cannot be empty." => "Folder name cannot be empty.", -"Folder name must not contain \"/\". Please choose a different name." => "Folder name must not contain \"/\". Please choose a different name.", "Error when creating the folder" => "Error when creating the folder", "Unable to set upload directory." => "Unable to set upload directory.", "Invalid Token" => "Invalid Token", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Missing a temporary folder", "Failed to write to disk" => "Failed to write to disk", "Not enough storage available" => "Not enough storage available", -"Upload failed. Could not get file info." => "Upload failed. Could not get file info.", "Upload failed. Could not find uploaded file" => "Upload failed. Could not find uploaded file", +"Upload failed. Could not get file info." => "Upload failed. Could not get file info.", "Invalid directory." => "Invalid directory.", "Files" => "Files", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Unable to upload {filename} as it is a directory or has 0 bytes", -"Not enough space available" => "Not enough space available", +"Total file size {size1} exceeds upload limit {size2}" => "Total file size {size1} exceeds upload limit {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Not enough free space, you are uploading {size1} but only {size2} is left", "Upload cancelled." => "Upload cancelled.", "Could not get result from server." => "Could not get result from server.", "File upload is in progress. Leaving the page now will cancel the upload." => "File upload is in progress. Leaving the page now will cancel the upload.", "URL cannot be empty" => "URL cannot be empty", -"In the home folder 'Shared' is a reserved filename" => "In the home folder 'Shared' is a reserved file name", "{new_name} already exists" => "{new_name} already exists", "Could not create file" => "Could not create file", "Could not create folder" => "Could not create folder", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Share", "Delete permanently" => "Delete permanently", "Rename" => "Rename", +"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.", "Pending" => "Pending", +"Error moving file." => "Error moving file.", +"Error moving file" => "Error moving file", +"Error" => "Error", "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.", +"Name" => "Name", +"Size" => "Size", +"Modified" => "Modified", "_%n folder_::_%n folders_" => array("%n folder","%n folders"), "_%n file_::_%n files_" => array("%n file","%n files"), -"{dirs} and {files}" => "{dirs} and {files}", "_Uploading %n file_::_Uploading %n files_" => array("Uploading %n file","Uploading %n files"), -"'.' is an invalid file name." => "'.' is an invalid file name.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Invalid name: '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed.", +"\"{name}\" is an invalid file name." => "\"{name}\" is an invalid file name.", "Your storage is full, files can not be updated or synced anymore!" => "Your storage is full, files can not be updated or synced anymore!", "Your storage is almost full ({usedSpacePercent}%)" => "Your storage is almost full ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Encryption App is enabled but your keys are not initialised, 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." => "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Invalid folder name. Usage of 'Shared' is reserved.", +"{dirs} and {files}" => "{dirs} and {files}", "%s could not be renamed" => "%s could not be renamed", -"Upload" => "Upload", +"Upload (max. %s)" => "Upload (max. %s)", "File handling" => "File handling", "Maximum upload size" => "Maximum upload size", "max. possible: " => "max. possible: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Upload too large", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "The files you are trying to upload exceed the maximum size for file uploads on this server.", "Files are being scanned, please wait." => "Files are being scanned, please wait.", -"Current scanning" => "Current scanning", -"Upgrading filesystem cache..." => "Upgrading filesystem cache..." +"Current scanning" => "Currently scanning" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/en_NZ.php b/apps/files/l10n/en_NZ.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/en_NZ.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/eo.php b/apps/files/l10n/eo.php index 81cfa03fd6..eebd94abc3 100644 --- a/apps/files/l10n/eo.php +++ b/apps/files/l10n/eo.php @@ -3,13 +3,12 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Ne eblis movi %s: dosiero kun ĉi tiu nomo jam ekzistas", "Could not move %s" => "Ne eblis movi %s", "File name cannot be empty." => "Dosiernomo devas ne malpleni.", -"File name must not contain \"/\". Please choose a different name." => "La dosieronomo ne devas enhavi “/”. Bonvolu elekti malsaman nomon.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nevalida nomo: “\\”, “/”, “<”, “>”, “:”, “\"”, “|”, “?” kaj “*” ne permesatas.", "The name %s is already used in the folder %s. Please choose a different name." => "La nomo %s jam uziĝas en la dosierujo %s. Bonvolu elekti malsaman nomon.", "Not a valid source" => "Nevalida fonto", "Error while downloading %s to %s" => "Eraris elŝuto de %s al %s", "Error when creating the file" => "Eraris la kreo de la dosiero", "Folder name cannot be empty." => "La dosierujnomo ne povas malpleni.", -"Folder name must not contain \"/\". Please choose a different name." => "La dosiernomo ne devas enhavi “/”. Bonvolu elekti malsaman nomon.", "Error when creating the folder" => "Eraris la kreo de la dosierujo", "Unable to set upload directory." => "Ne povis agordiĝi la alŝuta dosierujo.", "No file was uploaded. Unknown error" => "Neniu dosiero alŝutiĝis. Nekonata eraro.", @@ -21,12 +20,11 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Mankas provizora dosierujo.", "Failed to write to disk" => "Malsukcesis skribo al disko", "Not enough storage available" => "Ne haveblas sufiĉa memoro", -"Upload failed. Could not get file info." => "La alŝuto malsukcesis. Ne povis ekhaviĝi informo pri dosiero.", "Upload failed. Could not find uploaded file" => "La alŝuto malsukcesis. Ne troviĝis alŝutota dosiero.", +"Upload failed. Could not get file info." => "La alŝuto malsukcesis. Ne povis ekhaviĝi informo pri dosiero.", "Invalid directory." => "Nevalida dosierujo.", "Files" => "Dosieroj", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Ne povis alŝutiĝi {filename} ĉar ĝi estas dosierujo aŭ ĝi havas 0 duumokojn", -"Not enough space available" => "Ne haveblas sufiĉa spaco", "Upload cancelled." => "La alŝuto nuliĝis.", "Could not get result from server." => "Ne povis ekhaviĝi rezulto el la servilo.", "File upload is in progress. Leaving the page now will cancel the upload." => "Dosieralŝuto plenumiĝas. Lasi la paĝon nun nuligus la alŝuton.", @@ -37,26 +35,21 @@ $TRANSLATIONS = array( "Share" => "Kunhavigi", "Delete permanently" => "Forigi por ĉiam", "Rename" => "Alinomigi", -"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}", -"_Uploading %n file_::_Uploading %n files_" => array("Alŝutatas %n dosiero","Alŝutatas %n dosieroj"), -"'.' is an invalid file name." => "'.' ne estas valida dosiernomo.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nevalida nomo: “\\”, “/”, “<”, “>”, “:”, “\"”, “|”, “?” kaj “*” ne permesatas.", -"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.", +"Pending" => "Traktotaj", "Error moving file" => "Eraris movo de dosiero", "Error" => "Eraro", +"Could not rename file" => "Ne povis alinomiĝi dosiero", "Name" => "Nomo", "Size" => "Grando", "Modified" => "Modifita", +"_%n folder_::_%n folders_" => array("%n dosierujo","%n dosierujoj"), +"_%n file_::_%n files_" => array("%n dosiero","%n dosieroj"), +"_Uploading %n file_::_Uploading %n files_" => array("Alŝutatas %n dosiero","Alŝutatas %n dosieroj"), +"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}%)", +"{dirs} and {files}" => "{dirs} kaj {files}", "%s could not be renamed" => "%s ne povis alinomiĝi", -"Upload" => "Alŝuti", "File handling" => "Dosieradministro", "Maximum upload size" => "Maksimuma alŝutogrando", "max. possible: " => "maks. ebla: ", @@ -79,7 +72,6 @@ $TRANSLATIONS = array( "Upload too large" => "Alŝuto tro larĝa", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "La dosieroj, kiujn vi provas alŝuti, transpasas la maksimuman grandon por dosieralŝutoj en ĉi tiu servilo.", "Files are being scanned, please wait." => "Dosieroj estas skanataj, bonvolu atendi.", -"Current scanning" => "Nuna skano", -"Upgrading filesystem cache..." => "Ĝisdatiĝas dosiersistema kaŝmemoro..." +"Current scanning" => "Nuna skano" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/es.php b/apps/files/l10n/es.php index bfbb80e896..ba115e6af7 100644 --- a/apps/files/l10n/es.php +++ b/apps/files/l10n/es.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "No se pudo mover %s - Ya existe un archivo con ese nombre.", "Could not move %s" => "No se pudo mover %s", "File name cannot be empty." => "El nombre de archivo no puede estar vacío.", -"File name must not contain \"/\". Please choose a different name." => "El nombre del archivo, NO puede contener el simbolo\"/\", por favor elija un nombre diferente.", +"\"%s\" is an invalid file name." => "\"%s\" es un nombre de archivo inválido.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre inválido, los caracteres \"\\\", \"/\", \"<\", \">\", \":\", \"\", \"|\" \"?\" y \"*\" no están permitidos ", +"The target folder has been moved or deleted." => "La carpeta destino fue movida o eliminada.", "The name %s is already used in the folder %s. Please choose a different name." => "El nombre %s ya está en uso por la carpeta %s. Por favor elija uno diferente.", -"Not a valid source" => "No es un origen válido", -"Server is not allowed to open URLs, please check the server configuration" => "El servidor no puede acceder URLs; revise la configuración del servidor.", +"Not a valid source" => "No es una fuente válida", +"Server is not allowed to open URLs, please check the server configuration" => "La configuración del servidor no le permite abrir URLs, revísela.", "Error while downloading %s to %s" => "Error mientras se descargaba %s a %s", "Error when creating the file" => "Error al crear el archivo", "Folder name cannot be empty." => "El nombre de la carpeta no puede estar vacío.", -"Folder name must not contain \"/\". Please choose a different name." => "El nombre de la carpeta, NO puede contener el simbolo\"/\", por favor elija un nombre diferente.", "Error when creating the folder" => "Error al crear la carpeta.", "Unable to set upload directory." => "Incapaz de crear directorio de subida.", "Invalid Token" => "Token Inválido", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Falta la carpeta temporal", "Failed to write to disk" => "Falló al escribir al disco", "Not enough storage available" => "No hay suficiente espacio disponible", -"Upload failed. Could not get file info." => "Actualización fallida. No se pudo obtener información del archivo.", "Upload failed. Could not find uploaded file" => "Actualización fallida. No se pudo encontrar el archivo subido", +"Upload failed. Could not get file info." => "Actualización fallida. No se pudo obtener información del archivo.", "Invalid directory." => "Directorio inválido.", "Files" => "Archivos", "Unable to upload {filename} as it is a directory or has 0 bytes" => "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", -"Not enough space available" => "No hay suficiente espacio disponible", +"Total file size {size1} exceeds upload limit {size2}" => "El tamaño total del archivo {size1} excede el límite {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "No hay suficiente espacio libre. Quiere subir {size1} pero solo quedan {size2}", "Upload cancelled." => "Subida cancelada.", "Could not get result from server." => "No se pudo obtener respuesta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "La subida del archivo está en proceso. Si sale de la página ahora, la subida será cancelada.", "URL cannot be empty" => "La dirección URL no puede estar vacía", -"In the home folder 'Shared' is a reserved filename" => "En la carpeta de inicio, 'Shared' es un nombre reservado", "{new_name} already exists" => "{new_name} ya existe", "Could not create file" => "No se pudo crear el archivo", "Could not create folder" => "No se pudo crear la carpeta", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renombrar", +"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.", "Pending" => "Pendiente", +"Error moving file." => "Error al mover el archivo.", +"Error moving file" => "Error moviendo archivo", +"Error" => "Error", "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.", +"Error deleting file." => "Error al borrar el archivo", +"Name" => "Nombre", +"Size" => "Tamaño", +"Modified" => "Modificado", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), "_%n file_::_%n files_" => array("%n archivo","%n archivos"), -"{dirs} and {files}" => "{dirs} y {files}", "_Uploading %n file_::_Uploading %n files_" => array("Subiendo %n archivo","Subiendo %n archivos"), -"'.' is an invalid file name." => "'.' no es un nombre de archivo válido.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre inválido, los caracteres \"\\\", \"/\", \"<\", \">\", \":\", \"\", \"|\" \"?\" y \"*\" no están permitidos ", +"\"{name}\" is an invalid file name." => "\"{name}\" es un nombre de archivo inválido.", "Your storage is full, files can not be updated or synced anymore!" => "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!", "Your storage is almost full ({usedSpacePercent}%)" => "Su almacenamiento está casi lleno ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "La app de crifrado está habilitada pero tus claves no han sido inicializadas, por favor, cierra la sesión y vuelva a iniciarla de nuevo.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nombre de carpeta inválido. El uso de \"Shared\" esta reservado.", +"{dirs} and {files}" => "{dirs} y {files}", "%s could not be renamed" => "%s no pudo ser renombrado", -"Upload" => "Subir", +"Upload (max. %s)" => "Subida (máx. %s)", "File handling" => "Administración de archivos", "Maximum upload size" => "Tamaño máximo de subida", "max. possible: " => "máx. posible:", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Subida demasido grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los archivos que estás intentando subir sobrepasan el tamaño máximo permitido en este servidor.", "Files are being scanned, please wait." => "Los archivos están siendo escaneados, por favor espere.", -"Current scanning" => "Escaneo actual", -"Upgrading filesystem cache..." => "Actualizando caché del sistema de archivos..." +"Current scanning" => "Escaneo actual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/es_AR.php b/apps/files/l10n/es_AR.php index 78d6388cd9..7d1eb0fb4a 100644 --- a/apps/files/l10n/es_AR.php +++ b/apps/files/l10n/es_AR.php @@ -3,6 +3,14 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "No se pudo mover %s - Un archivo con este nombre ya existe", "Could not move %s" => "No se pudo mover %s ", "File name cannot be empty." => "El nombre del archivo no puede quedar vacío.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre invalido, '\\', '/', '<', '>', ':', '\"', '|', '?' y '*' no están permitidos.", +"The name %s is already used in the folder %s. Please choose a different name." => "El nombre %s está en uso en el directorio %s. Por favor elija un otro nombre.", +"Not a valid source" => "No es una fuente válida", +"Server is not allowed to open URLs, please check the server configuration" => "El servidor no está permitido abrir las URLs, por favor chequee la configuración del servidor", +"Error while downloading %s to %s" => "Error mientras se descargaba %s a %s", +"Error when creating the file" => "Error al crear el archivo", +"Folder name cannot be empty." => "El nombre del directorio no puede estar vacío.", +"Error when creating the folder" => "Error al crear el directorio", "Unable to set upload directory." => "No fue posible crear el directorio de subida.", "Invalid Token" => "Token Inválido", "No file was uploaded. Unknown error" => "El archivo no fue subido. Error desconocido", @@ -14,34 +22,41 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Falta un directorio temporal", "Failed to write to disk" => "Error al escribir en el disco", "Not enough storage available" => "No hay suficiente almacenamiento", +"Upload failed. Could not find uploaded file" => "Falló la carga. No se pudo encontrar el archivo subido.", +"Upload failed. Could not get file info." => "Falló la carga. No se pudo obtener la información del archivo.", "Invalid directory." => "Directorio inválido.", "Files" => "Archivos", -"Not enough space available" => "No hay suficiente espacio disponible", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "Imposible cargar {filename} puesto que es un directoro o tiene 0 bytes.", "Upload cancelled." => "La subida fue cancelada", +"Could not get result from server." => "No se pudo obtener resultados del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "La subida del archivo está en proceso. Si salís de la página ahora, la subida se cancelará.", +"URL cannot be empty" => "La URL no puede estar vacía", "{new_name} already exists" => "{new_name} ya existe", +"Could not create file" => "No se pudo crear el archivo", +"Could not create folder" => "No se pudo crear el directorio", +"Error fetching URL" => "Error al obtener la URL", "Share" => "Compartir", "Delete permanently" => "Borrar permanentemente", "Rename" => "Cambiar nombre", -"Pending" => "Pendientes", -"replaced {new_name} with {old_name}" => "se reemplazó {new_name} con {old_name}", -"undo" => "deshacer", -"_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), -"_%n file_::_%n files_" => array("%n archivo","%n archivos"), -"{dirs} and {files}" => "{carpetas} y {archivos}", -"_Uploading %n file_::_Uploading %n files_" => array("Subiendo %n archivo","Subiendo %n archivos"), -"'.' is an invalid file name." => "'.' es un nombre de archivo inválido.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre invalido, '\\', '/', '<', '>', ':', '\"', '|', '?' y '*' no están permitidos.", -"Your storage is full, files can not be updated or synced anymore!" => "El almacenamiento está lleno, los archivos no se pueden seguir actualizando ni sincronizando", -"Your storage is almost full ({usedSpacePercent}%)" => "El almacenamiento está casi lleno ({usedSpacePercent}%)", -"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.", +"Pending" => "Pendientes", +"Error moving file" => "Error moviendo el archivo", "Error" => "Error", +"Could not rename file" => "No se pudo renombrar el archivo", +"Error deleting file." => "Error al borrar el archivo.", "Name" => "Nombre", "Size" => "Tamaño", "Modified" => "Modificado", +"_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), +"_%n file_::_%n files_" => array("%n archivo","%n archivos"), +"_Uploading %n file_::_Uploading %n files_" => array("Subiendo %n archivo","Subiendo %n archivos"), +"Your storage is full, files can not be updated or synced anymore!" => "El almacenamiento está lleno, los archivos no se pueden seguir actualizando ni sincronizando", +"Your storage is almost full ({usedSpacePercent}%)" => "El almacenamiento está casi lleno ({usedSpacePercent}%)", +"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "La aplicación de encriptación está habilitada pero las llaves no fueron inicializadas, por favor termine y vuelva a iniciar la sesión", +"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.", +"{dirs} and {files}" => "{carpetas} y {archivos}", "%s could not be renamed" => "No se pudo renombrar %s", -"Upload" => "Subir", "File handling" => "Tratamiento de archivos", "Maximum upload size" => "Tamaño máximo de subida", "max. possible: " => "máx. posible:", @@ -51,19 +66,20 @@ $TRANSLATIONS = array( "Maximum input size for ZIP files" => "Tamaño máximo para archivos ZIP de entrada", "Save" => "Guardar", "New" => "Nuevo", +"New text file" => "Nuevo archivo de texto", "Text file" => "Archivo de texto", "New folder" => "Nueva Carpeta", "Folder" => "Carpeta", "From link" => "Desde enlace", "Deleted files" => "Archivos borrados", "Cancel upload" => "Cancelar subida", +"You don’t have permission to upload or create files here" => "No tienes permisos para subir o crear archivos aquí", "Nothing in here. Upload something!" => "No hay nada. ¡Subí contenido!", "Download" => "Descargar", "Delete" => "Borrar", "Upload too large" => "El tamaño del archivo que querés subir es demasiado grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los archivos que intentás subir sobrepasan el tamaño máximo ", "Files are being scanned, please wait." => "Se están escaneando los archivos, por favor esperá.", -"Current scanning" => "Escaneo actual", -"Upgrading filesystem cache..." => "Actualizando el cache del sistema de archivos" +"Current scanning" => "Escaneo actual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/es_CL.php b/apps/files/l10n/es_CL.php index 6f97758878..bdefea1d8c 100644 --- a/apps/files/l10n/es_CL.php +++ b/apps/files/l10n/es_CL.php @@ -1,9 +1,14 @@ "Archivos", +"Share" => "Compartir", +"Rename" => "Renombrar", +"Error" => "Error", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Upload" => "Subir" +"New folder" => "Nuevo directorio", +"Cancel upload" => "cancelar subida", +"Download" => "Descargar" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/es_CR.php b/apps/files/l10n/es_CR.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/es_CR.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/es_MX.php b/apps/files/l10n/es_MX.php index 0b7571defc..b6d06d9413 100644 --- a/apps/files/l10n/es_MX.php +++ b/apps/files/l10n/es_MX.php @@ -3,14 +3,13 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "No se pudo mover %s - Ya existe un archivo con ese nombre.", "Could not move %s" => "No se pudo mover %s", "File name cannot be empty." => "El nombre de archivo no puede estar vacío.", -"File name must not contain \"/\". Please choose a different name." => "El nombre del archivo, NO puede contener el simbolo\"/\", por favor elija un nombre diferente.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre inválido, los caracteres \"\\\", \"/\", \"<\", \">\", \":\", \"\", \"|\" \"?\" y \"*\" no están permitidos ", "The name %s is already used in the folder %s. Please choose a different name." => "El nombre %s ya está en uso por la carpeta %s. Por favor elija uno diferente.", "Not a valid source" => "No es un origen válido", "Server is not allowed to open URLs, please check the server configuration" => "El servidor no puede acceder URLs; revise la configuración del servidor.", "Error while downloading %s to %s" => "Error mientras se descargaba %s a %s", "Error when creating the file" => "Error al crear el archivo", "Folder name cannot be empty." => "El nombre de la carpeta no puede estar vacío.", -"Folder name must not contain \"/\". Please choose a different name." => "El nombre de la carpeta, NO puede contener el simbolo\"/\", por favor elija un nombre diferente.", "Error when creating the folder" => "Error al crear la carpeta.", "Unable to set upload directory." => "Incapaz de crear directorio de subida.", "Invalid Token" => "Token Inválido", @@ -23,17 +22,15 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Falta la carpeta temporal", "Failed to write to disk" => "Falló al escribir al disco", "Not enough storage available" => "No hay suficiente espacio disponible", -"Upload failed. Could not get file info." => "Actualización fallida. No se pudo obtener información del archivo.", "Upload failed. Could not find uploaded file" => "Actualización fallida. No se pudo encontrar el archivo subido", +"Upload failed. Could not get file info." => "Actualización fallida. No se pudo obtener información del archivo.", "Invalid directory." => "Directorio inválido.", "Files" => "Archivos", "Unable to upload {filename} as it is a directory or has 0 bytes" => "No ha sido posible subir {filename} porque es un directorio o tiene 0 bytes", -"Not enough space available" => "No hay suficiente espacio disponible", "Upload cancelled." => "Subida cancelada.", "Could not get result from server." => "No se pudo obtener respuesta del servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "La subida del archivo está en proceso. Si sale de la página ahora, la subida será cancelada.", "URL cannot be empty" => "La dirección URL no puede estar vacía", -"In the home folder 'Shared' is a reserved filename" => "En la carpeta de inicio, 'Shared' es un nombre reservado", "{new_name} already exists" => "{new_name} ya existe", "Could not create file" => "No se pudo crear el archivo", "Could not create folder" => "No se pudo crear la carpeta", @@ -41,31 +38,25 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renombrar", +"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.", "Pending" => "Pendiente", +"Error moving file" => "Error moviendo archivo", +"Error" => "Error", "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.", +"Name" => "Nombre", +"Size" => "Tamaño", +"Modified" => "Modificado", "_%n folder_::_%n folders_" => array("%n carpeta","%n carpetas"), "_%n file_::_%n files_" => array("%n archivo","%n archivos"), -"{dirs} and {files}" => "{dirs} y {files}", "_Uploading %n file_::_Uploading %n files_" => array("Subiendo %n archivo","Subiendo %n archivos"), -"'.' is an invalid file name." => "'.' no es un nombre de archivo válido.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre inválido, los caracteres \"\\\", \"/\", \"<\", \">\", \":\", \"\", \"|\" \"?\" y \"*\" no están permitidos ", "Your storage is full, files can not be updated or synced anymore!" => "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!", "Your storage is almost full ({usedSpacePercent}%)" => "Su almacenamiento está casi lleno ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "La aplicación de crifrado está habilitada pero tus claves no han sido inicializadas, por favor, cierra la sesión y vuelva a iniciarla de nuevo.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nombre de carpeta inválido. El uso de \"Shared\" esta reservado.", +"{dirs} and {files}" => "{dirs} y {files}", "%s could not be renamed" => "%s no pudo ser renombrado", -"Upload" => "Subir", "File handling" => "Administración de archivos", "Maximum upload size" => "Tamaño máximo de subida", "max. possible: " => "máx. posible:", @@ -89,7 +80,6 @@ $TRANSLATIONS = array( "Upload too large" => "Subida demasido grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los archivos que estás intentando subir sobrepasan el tamaño máximo permitido en este servidor.", "Files are being scanned, please wait." => "Los archivos están siendo escaneados, por favor espere.", -"Current scanning" => "Escaneo actual", -"Upgrading filesystem cache..." => "Actualizando caché del sistema de archivos..." +"Current scanning" => "Escaneo actual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/et_EE.php b/apps/files/l10n/et_EE.php index fd03152773..4956e3fb45 100644 --- a/apps/files/l10n/et_EE.php +++ b/apps/files/l10n/et_EE.php @@ -3,14 +3,15 @@ $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.", -"File name must not contain \"/\". Please choose a different name." => "Faili nimi ei tohi sisaldada \"/\". Palun vali mõni teine nimi.", +"\"%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", "Error while downloading %s to %s" => "Viga %s allalaadimisel %s", "Error when creating the file" => "Viga faili loomisel", "Folder name cannot be empty." => "Kataloogi nimi ei saa olla tühi.", -"Folder name must not contain \"/\". Please choose a different name." => "Kataloogi nimi ei tohi sisaldada \"/\". Palun vali mõni teine nimi.", "Error when creating the folder" => "Viga kataloogi loomisel", "Unable to set upload directory." => "Üleslaadimiste kausta määramine ebaõnnestus.", "Invalid Token" => "Vigane kontrollkood", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Ajutiste failide kaust puudub", "Failed to write to disk" => "Kettale kirjutamine ebaõnnestus", "Not enough storage available" => "Saadaval pole piisavalt ruumi", -"Upload failed. Could not get file info." => "Üleslaadimine ebaõnnestus. Faili info hankimine ebaõnnestus.", "Upload failed. Could not find uploaded file" => "Üleslaadimine ebaõnnestus. Üleslaetud faili ei leitud", +"Upload failed. Could not get file info." => "Üleslaadimine ebaõnnestus. Faili info hankimine ebaõnnestus.", "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", -"Not enough space available" => "Pole piisavalt ruumi", +"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.", "URL cannot be empty" => "URL ei saa olla tühi", -"In the home folder 'Shared' is a reserved filename" => "Kodukataloogis 'Shared' on reserveeritud failinimi", "{new_name} already exists" => "{new_name} on juba olemas", "Could not create file" => "Ei suuda luua faili", "Could not create folder" => "Ei suuda luua kataloogi", @@ -41,31 +42,27 @@ $TRANSLATIONS = array( "Share" => "Jaga", "Delete permanently" => "Kustuta jäädavalt", "Rename" => "Nimeta ümber", +"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. ", "Pending" => "Ootel", +"Error moving file" => "Viga faili eemaldamisel", +"Error" => "Viga", "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.", +"Name" => "Nimi", +"Size" => "Suurus", +"Modified" => "Muudetud", "_%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"), -"'.' is an invalid file name." => "'.' on vigane failinimi.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Vigane nimi, '\\', '/', '<', '>', ':', '\"', '|', '?' ja '*' pole lubatud.", +"\"{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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Vigane kausta nimi. Nime 'Shared' kasutamine on reserveeritud.", +"{dirs} and {files}" => "{dirs} ja {files}", "%s could not be renamed" => "%s ümbernimetamine ebaõnnestus", -"Upload" => "Lae üles", +"Upload (max. %s)" => "Üleslaadimine (max. %s)", "File handling" => "Failide käsitlemine", "Maximum upload size" => "Maksimaalne üleslaadimise suurus", "max. possible: " => "maks. võimalik: ", @@ -89,7 +86,6 @@ $TRANSLATIONS = array( "Upload too large" => "Üleslaadimine on liiga suur", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Failid, mida sa proovid üles laadida, ületab serveri poolt üleslaetavatele failidele määratud maksimaalse suuruse.", "Files are being scanned, please wait." => "Faile skannitakse, palun oota.", -"Current scanning" => "Praegune skannimine", -"Upgrading filesystem cache..." => "Failisüsteemi puhvri uuendamine..." +"Current scanning" => "Praegune skannimine" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/eu.php b/apps/files/l10n/eu.php index 5df480c2bc..3ad25d2fe4 100644 --- a/apps/files/l10n/eu.php +++ b/apps/files/l10n/eu.php @@ -3,13 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Ezin da %s mugitu - Izen hau duen fitxategia dagoeneko existitzen da", "Could not move %s" => "Ezin dira fitxategiak mugitu %s", "File name cannot be empty." => "Fitxategi izena ezin da hutsa izan.", -"File name must not contain \"/\". Please choose a different name." => "Fitxategi izenak ezin du \"/\" izan. Mesedez hautatu beste izen bat.", +"\"%s\" is an invalid file name." => "\"%s\" ez da fitxategi izen baliogarria.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "IZen aliogabea, '\\', '/', '<', '>', ':', '\"', '|', '?' eta '*' ez daude baimenduta.", +"The target folder has been moved or deleted." => "Jatorrizko karpeta mugitu edo ezabatu da.", "The name %s is already used in the folder %s. Please choose a different name." => "%s izena dagoeneko erabilita dago %s karpetan. Mesdez hautatu izen ezberdina.", "Not a valid source" => "Ez da jatorri baliogarria", +"Server is not allowed to open URLs, please check the server configuration" => "Zerbitzaria ez dago URLak irekitzeko baimendua, mesedez egiaztatu zerbitzariaren konfigurazioa", "Error while downloading %s to %s" => "Errorea %s %sra deskargatzerakoan", "Error when creating the file" => "Errorea fitxategia sortzerakoan", "Folder name cannot be empty." => "Karpeta izena ezin da hutsa izan.", -"Folder name must not contain \"/\". Please choose a different name." => "Karpeta izenak ezin du \"/\" izan. Mesedez hautatu beste izen bat.", "Error when creating the folder" => "Errorea karpeta sortzerakoan", "Unable to set upload directory." => "Ezin da igoera direktorioa ezarri.", "Invalid Token" => "Lekuko baliogabea", @@ -22,48 +24,46 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Aldi bateko karpeta falta da", "Failed to write to disk" => "Errore bat izan da diskoan idazterakoan", "Not enough storage available" => "Ez dago behar aina leku erabilgarri,", -"Upload failed. Could not get file info." => "Igoerak huts egin du. Ezin izan da fitxategiaren informazioa eskuratu.", "Upload failed. Could not find uploaded file" => "Igoerak huts egin du. Ezin izan da igotako fitxategia aurkitu", +"Upload failed. Could not get file info." => "Igoerak huts egin du. Ezin izan da fitxategiaren informazioa eskuratu.", "Invalid directory." => "Baliogabeko karpeta.", "Files" => "Fitxategiak", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Ezin da {filename} igo karpeta bat delako edo 0 byte dituelako", -"Not enough space available" => "Ez dago leku nahikorik.", +"Total file size {size1} exceeds upload limit {size2}" => "Fitxategiaren tamainak {size1} igotzeko muga {size2} gainditzen du", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Ez dago leku nahikorik, zu {size1} igotzen ari zara baina bakarrik {size2} libre dago", "Upload cancelled." => "Igoera ezeztatuta", "Could not get result from server." => "Ezin da zerbitzaritik emaitzik lortu", "File upload is in progress. Leaving the page now will cancel the upload." => "Fitxategien igoera martxan da. Orria orain uzteak igoera ezeztatutko du.", "URL cannot be empty" => "URLa ezin da hutsik egon", -"In the home folder 'Shared' is a reserved filename" => "Etxeko (home) karpetan 'Shared' erreserbatutako fitxategi izena da", "{new_name} already exists" => "{new_name} dagoeneko existitzen da", "Could not create file" => "Ezin izan da fitxategia sortu", "Could not create folder" => "Ezin izan da karpeta sortu", +"Error fetching URL" => "Errorea URLa eskuratzerakoan", "Share" => "Elkarbanatu", "Delete permanently" => "Ezabatu betirako", "Rename" => "Berrizendatu", +"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. ", "Pending" => "Zain", +"Error moving file." => "Errorea fitxategia mugitzean.", +"Error moving file" => "Errorea fitxategia mugitzean", +"Error" => "Errorea", "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.", +"Name" => "Izena", +"Size" => "Tamaina", +"Modified" => "Aldatuta", "_%n folder_::_%n folders_" => array("karpeta %n","%n karpeta"), "_%n file_::_%n files_" => array("fitxategi %n","%n fitxategi"), -"{dirs} and {files}" => "{dirs} eta {files}", "_Uploading %n file_::_Uploading %n files_" => array("Fitxategi %n igotzen","%n fitxategi igotzen"), -"'.' is an invalid file name." => "'.' ez da fitxategi izen baliogarria.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "IZen aliogabea, '\\', '/', '<', '>', ':', '\"', '|', '?' eta '*' ez daude baimenduta.", +"\"{name}\" is an invalid file name." => "\"{name}\" ez da fitxategi izen baliogarria.", "Your storage is full, files can not be updated or synced anymore!" => "Zure biltegiratzea beterik dago, ezingo duzu aurrerantzean fitxategirik igo edo sinkronizatu!", "Your storage is almost full ({usedSpacePercent}%)" => "Zure biltegiratzea nahiko beterik dago (%{usedSpacePercent})", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Enkriptazio aplikazioa gaituta dago baina zure gakoak ez daude konfiguratuta, mesedez saioa bukatu eta berriro hasi", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Baliogabeako karpeta izena. 'Shared' izena erreserbatuta dago.", +"{dirs} and {files}" => "{dirs} eta {files}", "%s could not be renamed" => "%s ezin da berrizendatu", -"Upload" => "Igo", +"Upload (max. %s)" => "Igo (max. %s)", "File handling" => "Fitxategien kudeaketa", "Maximum upload size" => "Igo daitekeen gehienezko tamaina", "max. possible: " => "max, posiblea:", @@ -87,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Igoera handiegia da", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Igotzen saiatzen ari zaren fitxategiak zerbitzari honek igotzeko onartzen duena baino handiagoak dira.", "Files are being scanned, please wait." => "Fitxategiak eskaneatzen ari da, itxoin mezedez.", -"Current scanning" => "Orain eskaneatzen ari da", -"Upgrading filesystem cache..." => "Fitxategi sistemaren katxea eguneratzen..." +"Current scanning" => "Orain eskaneatzen ari da" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/eu_ES.php b/apps/files/l10n/eu_ES.php new file mode 100644 index 0000000000..293e6de837 --- /dev/null +++ b/apps/files/l10n/eu_ES.php @@ -0,0 +1,10 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), +"Save" => "Gorde", +"Download" => "Deskargatu", +"Delete" => "Ezabatu" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/fa.php b/apps/files/l10n/fa.php index 4f3257bc07..ce4efe00e2 100644 --- a/apps/files/l10n/fa.php +++ b/apps/files/l10n/fa.php @@ -1,8 +1,9 @@ "%s نمی تواند حرکت کند - در حال حاضر پرونده با این نام وجود دارد. ", +"Could not move %s - File with this name already exists" => "%s نمی توان جابجا کرد - در حال حاضر پرونده با این نام وجود دارد. ", "Could not move %s" => "%s نمی تواند حرکت کند ", "File name cannot be empty." => "نام پرونده نمی تواند خالی باشد.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "نام نامعتبر ، '\\', '/', '<', '>', ':', '\"', '|', '?' و '*' مجاز نمی باشند.", "Unable to set upload directory." => "قادر به تنظیم پوشه آپلود نمی باشد.", "Invalid Token" => "رمز نامعتبر", "No file was uploaded. Unknown error" => "هیچ فایلی آپلود نشد.خطای ناشناس", @@ -16,30 +17,24 @@ $TRANSLATIONS = array( "Not enough storage available" => "فضای کافی در دسترس نیست", "Invalid directory." => "فهرست راهنما نامعتبر می باشد.", "Files" => "پرونده‌ها", -"Not enough space available" => "فضای کافی در دسترس نیست", "Upload cancelled." => "بار گذاری لغو شد", "File upload is in progress. Leaving the page now will cancel the upload." => "آپلودکردن پرونده در حال پیشرفت است. در صورت خروج از صفحه آپلود لغو میگردد. ", "{new_name} already exists" => "{نام _جدید} در حال حاضر وجود دارد.", "Share" => "اشتراک‌گذاری", "Delete permanently" => "حذف قطعی", "Rename" => "تغییرنام", -"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(""), -"'.' is an invalid file name." => "'.' یک نام پرونده نامعتبر است.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "نام نامعتبر ، '\\', '/', '<', '>', ':', '\"', '|', '?' و '*' مجاز نمی باشند.", -"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." => "دانلود شما در حال آماده شدن است. در صورتیکه پرونده ها بزرگ باشند ممکن است مدتی طول بکشد.", +"Pending" => "در انتظار", "Error" => "خطا", "Name" => "نام", "Size" => "اندازه", "Modified" => "تاریخ", +"_%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}%)", "%s could not be renamed" => "%s نمیتواند تغییر نام دهد.", -"Upload" => "بارگزاری", "File handling" => "اداره پرونده ها", "Maximum upload size" => "حداکثر اندازه بارگزاری", "max. possible: " => "حداکثرمقدارممکن:", @@ -61,7 +56,6 @@ $TRANSLATIONS = array( "Upload too large" => "سایز فایل برای آپلود زیاد است(م.تنظیمات در php.ini)", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "فایلها بیش از حد تعیین شده در این سرور هستند\nمترجم:با تغییر فایل php,ini میتوان این محدودیت را برطرف کرد", "Files are being scanned, please wait." => "پرونده ها در حال بازرسی هستند لطفا صبر کنید", -"Current scanning" => "بازرسی کنونی", -"Upgrading filesystem cache..." => "بهبود فایل سیستمی ذخیره گاه..." +"Current scanning" => "بازرسی کنونی" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/fi_FI.php b/apps/files/l10n/fi_FI.php index d1241b77da..2a5c02277f 100644 --- a/apps/files/l10n/fi_FI.php +++ b/apps/files/l10n/fi_FI.php @@ -3,15 +3,17 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Kohteen %s siirto ei onnistunut - Tiedosto samalla nimellä on jo olemassa", "Could not move %s" => "Kohteen %s siirto ei onnistunut", "File name cannot be empty." => "Tiedoston nimi ei voi olla tyhjä.", -"File name must not contain \"/\". Please choose a different name." => "Tiedoston nimessä ei saa olla merkkiä \"/\". Valitse toinen nimi.", +"\"%s\" is an invalid file name." => "\"%s\" on virheellinen tiedostonimi.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Virheellinen nimi, merkit '\\', '/', '<', '>', ':', '\"', '|', '?' ja '*' eivät ole sallittuja.", +"The target folder has been moved or deleted." => "Kohdekansio on siirretty tai poistettu.", "The name %s is already used in the folder %s. Please choose a different name." => "Nimi %s on jo käytössä kansiossa %s. Valitse toinen nimi.", "Not a valid source" => "Virheellinen lähde", "Server is not allowed to open URLs, please check the server configuration" => "Palvelimen ei ole lupa avata verkko-osoitteita. Tarkista palvelimen asetukset", "Error while downloading %s to %s" => "Virhe ladatessa kohdetta %s sijaintiin %s", "Error when creating the file" => "Virhe tiedostoa luotaessa", "Folder name cannot be empty." => "Kansion nimi ei voi olla tyhjä.", -"Folder name must not contain \"/\". Please choose a different name." => "Kansion nimessä ei saa olla merkkiä \"/\". Valitse toinen nimi.", "Error when creating the folder" => "Virhe kansiota luotaessa", +"Unable to set upload directory." => "Lähetyskansion asettaminen epäonnistui.", "No file was uploaded. Unknown error" => "Tiedostoa ei lähetetty. Tuntematon virhe", "There is no error, the file uploaded with success" => "Ei virheitä, tiedosto lähetettiin onnistuneesti", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Lähetetyn tiedoston koko ylittää php.ini-tiedoston upload_max_filesize-säännön:", @@ -22,10 +24,12 @@ $TRANSLATIONS = array( "Failed to write to disk" => "Levylle kirjoitus epäonnistui", "Not enough storage available" => "Tallennustilaa ei ole riittävästi käytettävissä", "Upload failed. Could not find uploaded file" => "Lähetys epäonnistui. Lähettävää tiedostoa ei löydetty.", +"Upload failed. Could not get file info." => "Lähetys epäonnistui. Lähettävää tiedostoa ei löydetty.", "Invalid directory." => "Virheellinen kansio.", "Files" => "Tiedostot", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Kohdetta {filename} ei voi lähettää, koska se on joko kansio tai sen koko on 0 tavua", -"Not enough space available" => "Tilaa ei ole riittävästi", +"Total file size {size1} exceeds upload limit {size2}" => "Yhteiskoko {size1} ylittää lähetysrajan {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Ei riittävästi vapaata tilaa. Lähetyksesi koko on {size1}, mutta vain {size2} on jäljellä", "Upload cancelled." => "Lähetys peruttu.", "Could not get result from server." => "Tuloksien saaminen palvelimelta ei onnistunut.", "File upload is in progress. Leaving the page now will cancel the upload." => "Tiedoston lähetys on meneillään. Sivulta poistuminen nyt peruu tiedoston lähetyksen.", @@ -37,28 +41,28 @@ $TRANSLATIONS = array( "Share" => "Jaa", "Delete permanently" => "Poista pysyvästi", "Rename" => "Nimeä uudelleen", -"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"), -"{dirs} and {files}" => "{dirs} ja {files}", -"_Uploading %n file_::_Uploading %n files_" => array("Lähetetään %n tiedosto","Lähetetään %n tiedostoa"), -"'.' is an invalid file name." => "'.' on virheellinen nimi tiedostolle.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Virheellinen nimi, merkit '\\', '/', '<', '>', ':', '\"', '|', '?' ja '*' eivät ole sallittuja.", -"Your storage is full, files can not be updated or synced anymore!" => "Tallennustila on loppu, tiedostoja ei voi enää päivittää tai synkronoida!", -"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.", +"Pending" => "Odottaa", +"Error moving file." => "Virhe tiedostoa siirrettäessä.", "Error moving file" => "Virhe tiedostoa siirrettäessä", "Error" => "Virhe", +"Could not rename file" => "Tiedoston nimeäminen uudelleen epäonnistui", +"Error deleting file." => "Virhe tiedostoa poistaessa.", "Name" => "Nimi", "Size" => "Koko", "Modified" => "Muokattu", -"Invalid folder name. Usage of 'Shared' is reserved." => "Virheellinen kansion nimi. 'Shared':n käyttö on varattu.", +"_%n folder_::_%n folders_" => array("%n kansio","%n kansiota"), +"_%n file_::_%n files_" => array("%n tiedosto","%n tiedostoa"), +"_Uploading %n file_::_Uploading %n files_" => array("Lähetetään %n tiedosto","Lähetetään %n tiedostoa"), +"\"{name}\" is an invalid file name." => "\"{name}\" on virheellinen tiedostonimi.", +"Your storage is full, files can not be updated or synced anymore!" => "Tallennustila on loppu, tiedostoja ei voi enää päivittää tai synkronoida!", +"Your storage is almost full ({usedSpacePercent}%)" => "Tallennustila on melkein loppu ({usedSpacePercent}%)", +"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Salaussovellus on käytössä, mutta salausavaimia ei ole alustettu. Ole hyvä ja kirjaudu sisään uudelleen.", +"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Salaussovelluksen salausavain on virheellinen. Ole hyvä ja päivitä salausavain henkilökohtaisissa asetuksissasi jotta voit taas avata salatuskirjoitetut tiedostosi.", +"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.", +"{dirs} and {files}" => "{dirs} ja {files}", "%s could not be renamed" => "kohteen %s nimeäminen uudelleen epäonnistui", -"Upload" => "Lähetä", +"Upload (max. %s)" => "Lähetys (enintään %s)", "File handling" => "Tiedostonhallinta", "Maximum upload size" => "Lähetettävän tiedoston suurin sallittu koko", "max. possible: " => "suurin mahdollinen:", @@ -82,7 +86,6 @@ $TRANSLATIONS = array( "Upload too large" => "Lähetettävä tiedosto on liian suuri", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Lähetettäväksi valitsemasi tiedostot ylittävät palvelimen salliman tiedostokoon rajan.", "Files are being scanned, please wait." => "Tiedostoja tarkistetaan, odota hetki.", -"Current scanning" => "Tämänhetkinen tutkinta", -"Upgrading filesystem cache..." => "Päivitetään tiedostojärjestelmän välimuistia..." +"Current scanning" => "Tämänhetkinen tutkinta" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/fr.php b/apps/files/l10n/fr.php index 73b8943477..3e61c782a5 100644 --- a/apps/files/l10n/fr.php +++ b/apps/files/l10n/fr.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Impossible de déplacer %s - Un fichier possédant ce nom existe déjà", "Could not move %s" => "Impossible de déplacer %s", "File name cannot be empty." => "Le nom de fichier ne peut être vide.", -"File name must not contain \"/\". Please choose a different name." => "Le nom de fichier ne doit pas contenir \"/\". Merci de choisir un nom différent.", +"\"%s\" is an invalid file name." => "\"%s\" n'est pas un nom de fichier valide.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nom invalide, les caractères '\\', '/', '<', '>', ':', '\"', '|', '?' et '*' ne sont pas autorisés.", +"The target folder has been moved or deleted." => "Le dossier cible a été déplacé ou supprimé.", "The name %s is already used in the folder %s. Please choose a different name." => "Le nom %s est déjà utilisé dans le dossier %s. Merci de choisir un nom différent.", "Not a valid source" => "La source n'est pas valide", "Server is not allowed to open URLs, please check the server configuration" => "Le serveur n'est pas autorisé à ouvrir des URL, veuillez vérifier la configuration du serveur", "Error while downloading %s to %s" => "Erreur pendant le téléchargement de %s à %s", "Error when creating the file" => "Erreur pendant la création du fichier", "Folder name cannot be empty." => "Le nom de dossier ne peux pas être vide.", -"Folder name must not contain \"/\". Please choose a different name." => "Le nom de dossier ne doit pas contenir \"/\". Merci de choisir un nom différent.", "Error when creating the folder" => "Erreur pendant la création du dossier", "Unable to set upload directory." => "Impossible de définir le dossier pour l'upload, charger.", "Invalid Token" => "Jeton non valide", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Absence de dossier temporaire.", "Failed to write to disk" => "Erreur d'écriture sur le disque", "Not enough storage available" => "Plus assez d'espace de stockage disponible", -"Upload failed. Could not get file info." => "L'envoi a échoué. Impossible d'obtenir les informations du fichier.", "Upload failed. Could not find uploaded file" => "L'envoi a échoué. Impossible de trouver le fichier envoyé.", +"Upload failed. Could not get file info." => "L'envoi a échoué. Impossible d'obtenir les informations du fichier.", "Invalid directory." => "Dossier invalide.", "Files" => "Fichiers", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Impossible d'envoyer {filename} car il s'agit d'un répertoire ou d'un fichier de taille nulle", -"Not enough space available" => "Espace disponible insuffisant", +"Total file size {size1} exceeds upload limit {size2}" => "La taille totale du fichier {size1} excède la taille maximale d'envoi {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Espace insuffisant : vous tentez d'envoyer {size1} mais seulement {size2} sont disponibles", "Upload cancelled." => "Envoi annulé.", "Could not get result from server." => "Ne peut recevoir les résultats du serveur.", "File upload is in progress. Leaving the page now will cancel the upload." => "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier.", "URL cannot be empty" => "L'URL ne peut pas être vide", -"In the home folder 'Shared' is a reserved filename" => "Dans le dossier home, 'Partagé' est un nom de fichier réservé", "{new_name} already exists" => "{new_name} existe déjà", "Could not create file" => "Impossible de créer le fichier", "Could not create folder" => "Impossible de créer le dossier", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Partager", "Delete permanently" => "Supprimer de façon définitive", "Rename" => "Renommer", +"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.", "Pending" => "En attente", +"Error moving file." => "Erreur lors du déplacement du fichier.", +"Error moving file" => "Erreur lors du déplacement du fichier", +"Error" => "Erreur", "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.", +"Name" => "Nom", +"Size" => "Taille", +"Modified" => "Modifié", "_%n folder_::_%n folders_" => array("%n dossier","%n dossiers"), "_%n file_::_%n files_" => array("%n fichier","%n fichiers"), -"{dirs} and {files}" => "{dirs} et {files}", "_Uploading %n file_::_Uploading %n files_" => array("Téléversement de %n fichier","Téléversement de %n fichiers"), -"'.' is an invalid file name." => "'.' n'est pas un nom de fichier valide.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nom invalide, les caractères '\\', '/', '<', '>', ':', '\"', '|', '?' et '*' ne sont pas autorisés.", +"\"{name}\" is an invalid file name." => "\"{name}\" n'est pas un nom de fichier valide.", "Your storage is full, files can not be updated or synced anymore!" => "Votre espage de stockage est plein, les fichiers ne peuvent plus être téléversés ou synchronisés !", "Your storage is almost full ({usedSpacePercent}%)" => "Votre espace de stockage est presque plein ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "L'application de chiffrement est activée mais vos clés ne sont pas initialisées, veuillez vous déconnecter et ensuite vous reconnecter.", "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é", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nom de dossier invalide. L'utilisation du mot 'Shared' est réservée.", +"{dirs} and {files}" => "{dirs} et {files}", "%s could not be renamed" => "%s ne peut être renommé", -"Upload" => "Envoyer", +"Upload (max. %s)" => "Envoi (max. %s)", "File handling" => "Gestion des fichiers", "Maximum upload size" => "Taille max. d'envoi", "max. possible: " => "Max. possible :", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Téléversement trop volumineux", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Les fichiers que vous essayez d'envoyer dépassent la taille maximale permise par ce serveur.", "Files are being scanned, please wait." => "Les fichiers sont en cours d'analyse, veuillez patienter.", -"Current scanning" => "Analyse en cours", -"Upgrading filesystem cache..." => "Mise à niveau du cache du système de fichier" +"Current scanning" => "Analyse en cours" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files/l10n/gl.php b/apps/files/l10n/gl.php index 1d22691d93..66d981c454 100644 --- a/apps/files/l10n/gl.php +++ b/apps/files/l10n/gl.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Non foi posíbel mover %s; Xa existe un ficheiro con ese nome.", "Could not move %s" => "Non foi posíbel mover %s", "File name cannot be empty." => "O nome de ficheiro non pode estar baleiro", -"File name must not contain \"/\". Please choose a different name." => "O nome do ficheiro non pode conter «/». Escolla outro nome.", +"\"%s\" is an invalid file name." => "«%s» é un nome incorrecto de ficheiro.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome incorrecto, non se permite «\\», «/», «<», «>», «:», «\"», «|», «?» e «*».", +"The target folder has been moved or deleted." => "O cartafol de destino foi movido ou eliminado.", "The name %s is already used in the folder %s. Please choose a different name." => "Xa existe o nome %s no cartafol %s. Escolla outro nome.", "Not a valid source" => "Esta orixe non é correcta", "Server is not allowed to open URLs, please check the server configuration" => "O servidor non ten permisos para abrir os enderezos URL, comprobe a configuración do servidor", "Error while downloading %s to %s" => "Produciuse un erro ao descargar %s en %s", "Error when creating the file" => "Produciuse un erro ao crear o ficheiro", "Folder name cannot be empty." => "O nome de cartafol non pode estar baleiro.", -"Folder name must not contain \"/\". Please choose a different name." => "O nome do cartafol non pode conter «/». Escolla outro nome.", "Error when creating the folder" => "Produciuse un erro ao crear o cartafol", "Unable to set upload directory." => "Non é posíbel configurar o directorio de envíos.", "Invalid Token" => "Marca incorrecta", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Falta o cartafol temporal", "Failed to write to disk" => "Produciuse un erro ao escribir no disco", "Not enough storage available" => "Non hai espazo de almacenamento abondo", -"Upload failed. Could not get file info." => "O envío fracasou. Non foi posíbel obter información do ficheiro.", "Upload failed. Could not find uploaded file" => "O envío fracasou. Non foi posíbel atopar o ficheiro enviado", +"Upload failed. Could not get file info." => "O envío fracasou. Non foi posíbel obter información do ficheiro.", "Invalid directory." => "O directorio é incorrecto.", "Files" => "Ficheiros", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Non é posíbel enviar {filename}, xa que ou é un directorio ou ten 0 bytes", -"Not enough space available" => "O espazo dispoñíbel é insuficiente", +"Total file size {size1} exceeds upload limit {size2}" => "O tamaño total do ficheiro {size1} excede do límite de envío {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Non hai espazo libre abondo, o seu envío é de {size1} mais só dispón de {size2}", "Upload cancelled." => "Envío cancelado.", "Could not get result from server." => "Non foi posíbel obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "O envío do ficheiro está en proceso. Saír agora da páxina cancelará o envío.", "URL cannot be empty" => "O URL non pode quedar en branco.", -"In the home folder 'Shared' is a reserved filename" => "«Shared» dentro do cartafol persoal é un nome reservado", "{new_name} already exists" => "Xa existe un {new_name}", "Could not create file" => "Non foi posíbel crear o ficheiro", "Could not create folder" => "Non foi posíbel crear o cartafol", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Compartir", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renomear", +"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.", "Pending" => "Pendentes", +"Error moving file." => "Produciuse un erro ao mover o ficheiro.", +"Error moving file" => "Produciuse un erro ao mover o ficheiro", +"Error" => "Erro", "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.", +"Name" => "Nome", +"Size" => "Tamaño", +"Modified" => "Modificado", "_%n folder_::_%n folders_" => array("%n cartafol","%n cartafoles"), "_%n file_::_%n files_" => array("%n ficheiro","%n ficheiros"), -"{dirs} and {files}" => "{dirs} e {files}", "_Uploading %n file_::_Uploading %n files_" => array("Cargando %n ficheiro","Cargando %n ficheiros"), -"'.' is an invalid file name." => "«.» é un nome de ficheiro incorrecto", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome incorrecto, non se permite «\\», «/», «<», «>», «:», «\"», «|», «?» e «*».", +"\"{name}\" is an invalid file name." => "«{name}» é un nome incorrecto de ficheiro.", "Your storage is full, files can not be updated or synced anymore!" => "O seu espazo de almacenamento está cheo, non é posíbel actualizar ou sincronizar máis os ficheiros!", "Your storage is almost full ({usedSpacePercent}%)" => "O seu espazo de almacenamento está case cheo ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "O aplicativo de cifrado está activado, mais as chaves non foron inicializadas, saia da sesión e volva a acceder de novo", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nome de cartafol non válido. O uso de «Shared» está reservado.", +"{dirs} and {files}" => "{dirs} e {files}", "%s could not be renamed" => "%s non pode cambiar de nome", -"Upload" => "Enviar", +"Upload (max. %s)" => "Envío (máx. %s)", "File handling" => "Manexo de ficheiro", "Maximum upload size" => "Tamaño máximo do envío", "max. possible: " => "máx. posíbel: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Envío demasiado grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os ficheiros que tenta enviar exceden do tamaño máximo permitido neste servidor", "Files are being scanned, please wait." => "Estanse analizando os ficheiros. Agarde.", -"Current scanning" => "Análise actual", -"Upgrading filesystem cache..." => "Anovando a caché do sistema de ficheiros..." +"Current scanning" => "Análise actual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/he.php b/apps/files/l10n/he.php index 0cdb178254..7f15517654 100644 --- a/apps/files/l10n/he.php +++ b/apps/files/l10n/he.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "לא ניתן להעביר את %s - קובץ בשם הזה כבר קיים", "Could not move %s" => "לא ניתן להעביר את %s", "File name cannot be empty." => "שם קובץ אינו יכול להיות ריק", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "השם שגוי, אסור להשתמש בתווים '\\', '/', '<', '>', ':', '\"', '|', '?' ו־'*'.", "No file was uploaded. Unknown error" => "לא הועלה קובץ. טעות בלתי מזוהה.", "There is no error, the file uploaded with success" => "לא התרחשה שגיאה, הקובץ הועלה בהצלחה", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "הקבצים שנשלחו חורגים מהגודל שצוין בהגדרה upload_max_filesize שבקובץ php.ini:", @@ -23,18 +24,14 @@ $TRANSLATIONS = array( "Delete permanently" => "מחק לצמיתות", "Rename" => "שינוי שם", "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("",""), -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "השם שגוי, אסור להשתמש בתווים '\\', '/', '<', '>', ':', '\"', '|', '?' ו־'*'.", -"Your storage is almost full ({usedSpacePercent}%)" => "שטח האחסון שלך כמעט מלא ({usedSpacePercent}%)", "Error" => "שגיאה", "Name" => "שם", "Size" => "גודל", "Modified" => "זמן שינוי", -"Upload" => "העלאה", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), +"Your storage is almost full ({usedSpacePercent}%)" => "שטח האחסון שלך כמעט מלא ({usedSpacePercent}%)", "File handling" => "טיפול בקבצים", "Maximum upload size" => "גודל העלאה מקסימלי", "max. possible: " => "המרבי האפשרי: ", diff --git a/apps/files/l10n/hi.php b/apps/files/l10n/hi.php index ae01bfc47e..13fded2671 100644 --- a/apps/files/l10n/hi.php +++ b/apps/files/l10n/hi.php @@ -1,11 +1,10 @@ "साझा करें", +"Error" => "त्रुटि", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "त्रुटि", -"Upload" => "अपलोड ", "Save" => "सहेजें" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/hi_IN.php b/apps/files/l10n/hi_IN.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/hi_IN.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/hr.php b/apps/files/l10n/hr.php index 5048a15c8b..4e8deeed51 100644 --- a/apps/files/l10n/hr.php +++ b/apps/files/l10n/hr.php @@ -12,15 +12,13 @@ $TRANSLATIONS = array( "Share" => "Podijeli", "Rename" => "Promjeni ime", "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", -"Upload" => "Učitaj", +"_%n folder_::_%n folders_" => array("","",""), +"_%n file_::_%n files_" => array("","",""), +"_Uploading %n file_::_Uploading %n files_" => array("","",""), "File handling" => "datoteka za rukovanje", "Maximum upload size" => "Maksimalna veličina prijenosa", "max. possible: " => "maksimalna moguća: ", diff --git a/apps/files/l10n/hu_HU.php b/apps/files/l10n/hu_HU.php index 22c3926ed1..3cfb547261 100644 --- a/apps/files/l10n/hu_HU.php +++ b/apps/files/l10n/hu_HU.php @@ -3,14 +3,13 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "%s áthelyezése nem sikerült - már létezik másik fájl ezzel a névvel", "Could not move %s" => "Nem sikerült %s áthelyezése", "File name cannot be empty." => "A fájlnév nem lehet semmi.", -"File name must not contain \"/\". Please choose a different name." => "Az állomány neve nem tartalmazhatja a \"/\" karaktert. Kérem válasszon másik nevet!", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Érvénytelen elnevezés. Ezek a karakterek nem használhatók: '\\', '/', '<', '>', ':', '\"', '|', '?' és '*'", "The name %s is already used in the folder %s. Please choose a different name." => "A %s név már létezik a %s mappában. Kérem válasszon másik nevet!", "Not a valid source" => "A kiinduló állomány érvénytelen", "Server is not allowed to open URLs, please check the server configuration" => "A kiszolgálón nincs engedélyezve URL-ek megnyitása, kérem ellenőrizze a beállításokat", "Error while downloading %s to %s" => "Hiba történt miközben %s-t letöltöttük %s-be", "Error when creating the file" => "Hiba történt az állomány létrehozásakor", "Folder name cannot be empty." => "A mappa neve nem maradhat kitöltetlenül", -"Folder name must not contain \"/\". Please choose a different name." => "A mappa neve nem tartalmazhatja a \"/\" karaktert. Kérem válasszon másik nevet!", "Error when creating the folder" => "Hiba történt a mappa létrehozásakor", "Unable to set upload directory." => "Nem található a mappa, ahova feltölteni szeretne.", "Invalid Token" => "Hibás mappacím", @@ -23,17 +22,15 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Hiányzik egy ideiglenes mappa", "Failed to write to disk" => "Nem sikerült a lemezre történő írás", "Not enough storage available" => "Nincs elég szabad hely.", -"Upload failed. Could not get file info." => "A feltöltés nem sikerült. Az állományt leíró információk nem érhetők el.", "Upload failed. Could not find uploaded file" => "A feltöltés nem sikerült. Nem található a feltöltendő állomány.", +"Upload failed. Could not get file info." => "A feltöltés nem sikerült. Az állományt leíró információk nem érhetők el.", "Invalid directory." => "Érvénytelen mappa.", "Files" => "Fájlok", "Unable to upload {filename} as it is a directory or has 0 bytes" => "A(z) {filename} állomány nem tölthető fel, mert ez vagy egy mappa, vagy pedig 0 bájtból áll.", -"Not enough space available" => "Nincs elég szabad hely", "Upload cancelled." => "A feltöltést megszakítottuk.", "Could not get result from server." => "A kiszolgálótól nem kapható meg az eredmény.", "File upload is in progress. Leaving the page now will cancel the upload." => "Fájlfeltöltés van folyamatban. Az oldal elhagyása megszakítja a feltöltést.", "URL cannot be empty" => "Az URL-cím nem maradhat kitöltetlenül", -"In the home folder 'Shared' is a reserved filename" => "A kiindulási mappában a 'Shared' egy belső használatra fenntartott név", "{new_name} already exists" => "{new_name} már létezik", "Could not create file" => "Az állomány nem hozható létre", "Could not create folder" => "A mappa nem hozható létre", @@ -41,31 +38,25 @@ $TRANSLATIONS = array( "Share" => "Megosztás", "Delete permanently" => "Végleges törlés", "Rename" => "Átnevezés", +"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.", "Pending" => "Folyamatban", +"Error moving file" => "Az állomány áthelyezése nem sikerült.", +"Error" => "Hiba", "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.", +"Name" => "Név", +"Size" => "Méret", +"Modified" => "Módosítva", "_%n folder_::_%n folders_" => array("%n mappa","%n mappa"), "_%n file_::_%n files_" => array("%n állomány","%n állomány"), -"{dirs} and {files}" => "{dirs} és {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n állomány feltöltése","%n állomány feltöltése"), -"'.' is an invalid file name." => "'.' fájlnév érvénytelen.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Érvénytelen elnevezés. Ezek a karakterek nem használhatók: '\\', '/', '<', '>', ':', '\"', '|', '?' és '*'", "Your storage is full, files can not be updated or synced anymore!" => "A tároló tele van, a fájlok nem frissíthetőek vagy szinkronizálhatóak a jövőben.", "Your storage is almost full ({usedSpacePercent}%)" => "A tároló majdnem tele van ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Az állományok titkosítása engedélyezve van, de az Ön titkos kulcsai nincsenek beállítva. Ezért kérjük, hogy jelentkezzen ki, és lépjen be újra!", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Érvénytelen mappanév. A 'Shared' a rendszer számára fenntartott elnevezés.", +"{dirs} and {files}" => "{dirs} és {files}", "%s could not be renamed" => "%s átnevezése nem sikerült", -"Upload" => "Feltöltés", "File handling" => "Fájlkezelés", "Maximum upload size" => "Maximális feltölthető fájlméret", "max. possible: " => "max. lehetséges: ", @@ -89,7 +80,6 @@ $TRANSLATIONS = array( "Upload too large" => "A feltöltés túl nagy", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "A feltöltendő állományok mérete meghaladja a kiszolgálón megengedett maximális méretet.", "Files are being scanned, please wait." => "A fájllista ellenőrzése zajlik, kis türelmet!", -"Current scanning" => "Ellenőrzés alatt", -"Upgrading filesystem cache..." => "A fájlrendszer gyorsítótárának frissítése zajlik..." +"Current scanning" => "Ellenőrzés alatt" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ia.php b/apps/files/l10n/ia.php index 82fd2e658d..51d433258b 100644 --- a/apps/files/l10n/ia.php +++ b/apps/files/l10n/ia.php @@ -5,18 +5,18 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Manca un dossier temporari", "Files" => "Files", "Share" => "Compartir", -"_%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", -"Upload" => "Incargar", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "Maximum upload size" => "Dimension maxime de incargamento", "Save" => "Salveguardar", "New" => "Nove", "Text file" => "File de texto", +"New folder" => "Nove dossier", "Folder" => "Dossier", "Nothing in here. Upload something!" => "Nihil hic. Incarga alcun cosa!", "Download" => "Discargar", diff --git a/apps/files/l10n/id.php b/apps/files/l10n/id.php index 4e254ff6f6..e4a2529e5e 100644 --- a/apps/files/l10n/id.php +++ b/apps/files/l10n/id.php @@ -3,13 +3,12 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Tidak dapat memindahkan %s - Berkas dengan nama ini sudah ada", "Could not move %s" => "Tidak dapat memindahkan %s", "File name cannot be empty." => "Nama berkas tidak boleh kosong.", -"File name must not contain \"/\". Please choose a different name." => "Nama berkas tidak boleh mengandung \"/\". Silakan pilih nama yang berbeda.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nama tidak valid, karakter '\\', '/', '<', '>', ':', '\"', '|', '?' dan '*' tidak diizinkan.", "The name %s is already used in the folder %s. Please choose a different name." => "Nama %s sudah digunakan dalam folder %s. Silakan pilih nama yang berbeda.", "Not a valid source" => "Sumber tidak sah", "Error while downloading %s to %s" => "Galat saat mengunduh %s ke %s", "Error when creating the file" => "Galat saat membuat berkas", "Folder name cannot be empty." => "Nama folder tidak bolh kosong.", -"Folder name must not contain \"/\". Please choose a different name." => "Nama folder tidak boleh mengandung \"/\". Silakan pilih nama yang berbeda.", "Error when creating the folder" => "Galat saat membuat folder", "Unable to set upload directory." => "Tidak dapat mengatur folder unggah", "Invalid Token" => "Token tidak sah", @@ -22,48 +21,40 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Folder sementara tidak ada", "Failed to write to disk" => "Gagal menulis ke disk", "Not enough storage available" => "Ruang penyimpanan tidak mencukupi", -"Upload failed. Could not get file info." => "Unggah gagal. Tidak mendapatkan informasi berkas.", "Upload failed. Could not find uploaded file" => "Unggah gagal. Tidak menemukan berkas yang akan diunggah", +"Upload failed. Could not get file info." => "Unggah gagal. Tidak mendapatkan informasi berkas.", "Invalid directory." => "Direktori tidak valid.", "Files" => "Berkas", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Tidak dapat mengunggah {filename} karena ini sebuah direktori atau memiliki ukuran 0 byte", -"Not enough space available" => "Ruang penyimpanan tidak mencukupi", "Upload cancelled." => "Pengunggahan dibatalkan.", "Could not get result from server." => "Tidak mendapatkan hasil dari server.", "File upload is in progress. Leaving the page now will cancel the upload." => "Berkas sedang diunggah. Meninggalkan halaman ini akan membatalkan proses.", "URL cannot be empty" => "URL tidak boleh kosong", -"In the home folder 'Shared' is a reserved filename" => "Pada folder home, 'Shared' adalah nama berkas yang sudah digunakan", "{new_name} already exists" => "{new_name} sudah ada", "Could not create file" => "Tidak dapat membuat berkas", "Could not create folder" => "Tidak dapat membuat folder", "Share" => "Bagikan", "Delete permanently" => "Hapus secara permanen", "Rename" => "Ubah nama", +"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.", "Pending" => "Menunggu", +"Error moving file" => "Galat saat memindahkan berkas", +"Error" => "Galat", "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.", +"Name" => "Nama", +"Size" => "Ukuran", +"Modified" => "Dimodifikasi", "_%n folder_::_%n folders_" => array("%n folder"), "_%n file_::_%n files_" => array("%n berkas"), -"{dirs} and {files}" => "{dirs} dan {files}", "_Uploading %n file_::_Uploading %n files_" => array("Mengunggah %n berkas"), -"'.' is an invalid file name." => "'.' bukan nama berkas yang valid.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nama tidak valid, karakter '\\', '/', '<', '>', ':', '\"', '|', '?' dan '*' tidak diizinkan.", "Your storage is full, files can not be updated or synced anymore!" => "Ruang penyimpanan Anda penuh, berkas tidak dapat diperbarui atau disinkronkan lagi!", "Your storage is almost full ({usedSpacePercent}%)" => "Ruang penyimpanan hampir penuh ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Aplikasi Enskripsi telah diaktifkan tetapi kunci tidak diinisialisasi, silakan log-out dan log-in lagi", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nama folder tidak sah. Menggunakan 'Shared' sudah digunakan.", +"{dirs} and {files}" => "{dirs} dan {files}", "%s could not be renamed" => "%s tidak dapat diubah nama", -"Upload" => "Unggah", "File handling" => "Penanganan berkas", "Maximum upload size" => "Ukuran pengunggahan maksimum", "max. possible: " => "Kemungkinan maks.:", @@ -87,7 +78,6 @@ $TRANSLATIONS = array( "Upload too large" => "Yang diunggah terlalu besar", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Berkas yang dicoba untuk diunggah melebihi ukuran maksimum pengunggahan berkas di server ini.", "Files are being scanned, please wait." => "Berkas sedang dipindai, silakan tunggu.", -"Current scanning" => "Yang sedang dipindai", -"Upgrading filesystem cache..." => "Meningkatkan tembolok sistem berkas..." +"Current scanning" => "Yang sedang dipindai" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/is.php b/apps/files/l10n/is.php index 5c5cc7d5d7..82b3db81d6 100644 --- a/apps/files/l10n/is.php +++ b/apps/files/l10n/is.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Gat ekki fært %s - Skrá með þessu nafni er þegar til", "Could not move %s" => "Gat ekki fært %s", "File name cannot be empty." => "Nafn skráar má ekki vera tómt", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ógilt nafn, táknin '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' eru ekki leyfð.", "No file was uploaded. Unknown error" => "Engin skrá var send inn. Óþekkt villa.", "There is no error, the file uploaded with success" => "Engin villa, innsending heppnaðist", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Innsend skrá er stærri en upload_max stillingin í php.ini:", @@ -13,25 +14,19 @@ $TRANSLATIONS = array( "Failed to write to disk" => "Tókst ekki að skrifa á disk", "Invalid directory." => "Ógild mappa.", "Files" => "Skrár", -"Not enough space available" => "Ekki nægt pláss tiltækt", "Upload cancelled." => "Hætt við innsendingu.", "File upload is in progress. Leaving the page now will cancel the upload." => "Innsending í gangi. Ef þú ferð af þessari síðu mun innsending misheppnast.", "{new_name} already exists" => "{new_name} er þegar til", "Share" => "Deila", "Rename" => "Endurskýra", "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("",""), -"'.' is an invalid file name." => "'.' er ekki leyfilegt nafn.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ógilt nafn, táknin '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' eru ekki leyfð.", "Error" => "Villa", "Name" => "Nafn", "Size" => "Stærð", "Modified" => "Breytt", -"Upload" => "Senda inn", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "File handling" => "Meðhöndlun skrár", "Maximum upload size" => "Hámarks stærð innsendingar", "max. possible: " => "hámark mögulegt: ", diff --git a/apps/files/l10n/it.php b/apps/files/l10n/it.php index 2a10e9977f..d55c800916 100644 --- a/apps/files/l10n/it.php +++ b/apps/files/l10n/it.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Impossibile spostare %s - un file con questo nome esiste già", "Could not move %s" => "Impossibile spostare %s", "File name cannot be empty." => "Il nome del file non può essere vuoto.", -"File name must not contain \"/\". Please choose a different name." => "Il nome del file non può contenere il carattere \"/\". Scegli un nome diverso.", +"\"%s\" is an invalid file name." => "\"%s\" non è un nome file valido.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome non valido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' non sono consentiti.", +"The target folder has been moved or deleted." => "La cartella di destinazione è stata spostata o eliminata.", "The name %s is already used in the folder %s. Please choose a different name." => "Il nome %s è attualmente in uso nella cartella %s. Scegli un nome diverso.", "Not a valid source" => "Non è una sorgente valida", "Server is not allowed to open URLs, please check the server configuration" => "Al server non è permesso aprire URL, controlla la configurazione del server", "Error while downloading %s to %s" => "Errore durante lo scaricamento di %s su %s", "Error when creating the file" => "Errore durante la creazione del file", "Folder name cannot be empty." => "Il nome della cartella non può essere vuoto.", -"Folder name must not contain \"/\". Please choose a different name." => "Il nome della cartella non può contenere il carattere \"/\". Scegli un nome diverso.", "Error when creating the folder" => "Errore durante la creazione della cartella", "Unable to set upload directory." => "Impossibile impostare una cartella di caricamento.", "Invalid Token" => "Token non valido", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Manca una cartella temporanea", "Failed to write to disk" => "Scrittura su disco non riuscita", "Not enough storage available" => "Spazio di archiviazione insufficiente", -"Upload failed. Could not get file info." => "Caricamento non riuscito. Impossibile ottenere informazioni sul file.", "Upload failed. Could not find uploaded file" => "Caricamento non riuscito. Impossibile trovare il file caricato.", +"Upload failed. Could not get file info." => "Caricamento non riuscito. Impossibile ottenere informazioni sul file.", "Invalid directory." => "Cartella non valida.", "Files" => "File", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Impossibile caricare {filename} poiché è una cartella oppure ha una dimensione di 0 byte.", -"Not enough space available" => "Spazio disponibile insufficiente", +"Total file size {size1} exceeds upload limit {size2}" => "La dimensione totale del file {size1} supera il limite di caricamento {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Spazio insufficiente, stai caricando {size1}, ma è rimasto solo {size2}", "Upload cancelled." => "Invio annullato", "Could not get result from server." => "Impossibile ottenere il risultato dal server.", "File upload is in progress. Leaving the page now will cancel the upload." => "Caricamento del file in corso. La chiusura della pagina annullerà il caricamento.", "URL cannot be empty" => "L'URL non può essere vuoto.", -"In the home folder 'Shared' is a reserved filename" => "Nella cartella home 'Shared' è un nome riservato", "{new_name} already exists" => "{new_name} esiste già", "Could not create file" => "Impossibile creare il file", "Could not create folder" => "Impossibile creare la cartella", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Condividi", "Delete permanently" => "Elimina definitivamente", "Rename" => "Rinomina", +"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.", "Pending" => "In corso", +"Error moving file." => "Errore durante lo spostamento del file.", +"Error moving file" => "Errore durante lo spostamento del file", +"Error" => "Errore", "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.", +"Name" => "Nome", +"Size" => "Dimensione", +"Modified" => "Modificato", "_%n folder_::_%n folders_" => array("%n cartella","%n cartelle"), "_%n file_::_%n files_" => array("%n file","%n file"), -"{dirs} and {files}" => "{dirs} e {files}", "_Uploading %n file_::_Uploading %n files_" => array("Caricamento di %n file in corso","Caricamento di %n file in corso"), -"'.' is an invalid file name." => "'.' non è un nome file valido.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome non valido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' non sono consentiti.", +"\"{name}\" is an invalid file name." => "\"{name}\" non è un nome file valido.", "Your storage is full, files can not be updated or synced anymore!" => "Lo spazio di archiviazione è pieno, i file non possono essere più aggiornati o sincronizzati!", "Your storage is almost full ({usedSpacePercent}%)" => "Lo spazio di archiviazione è quasi pieno ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "L'applicazione di cifratura è abilitata, ma le chiavi non sono state inizializzate, disconnettiti ed effettua nuovamente l'accesso", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nome della cartella non valido. L'uso di 'Shared' è riservato.", +"{dirs} and {files}" => "{dirs} e {files}", "%s could not be renamed" => "%s non può essere rinominato", -"Upload" => "Carica", +"Upload (max. %s)" => "Carica (massimo %s)", "File handling" => "Gestione file", "Maximum upload size" => "Dimensione massima upload", "max. possible: " => "numero mass.: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Caricamento troppo grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "I file che stai provando a caricare superano la dimensione massima consentita su questo server.", "Files are being scanned, please wait." => "Scansione dei file in corso, attendi", -"Current scanning" => "Scansione corrente", -"Upgrading filesystem cache..." => "Aggiornamento della cache del filesystem in corso..." +"Current scanning" => "Scansione corrente" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ja.php b/apps/files/l10n/ja.php new file mode 100644 index 0000000000..0b00594d71 --- /dev/null +++ b/apps/files/l10n/ja.php @@ -0,0 +1,92 @@ + "%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を開くことは許されません。サーバーの設定をチェックしてください。", +"Error while downloading %s to %s" => "%s から %s へのダウンロードエラー", +"Error when creating the file" => "ファイルの生成エラー", +"Folder name cannot be empty." => "フォルダー名は空にできません", +"Error when creating the folder" => "フォルダーの生成エラー", +"Unable to set upload directory." => "アップロードディレクトリを設定できません。", +"Invalid Token" => "無効なトークン", +"No file was uploaded. Unknown error" => "ファイルは何もアップロードされていません。不明なエラー", +"There is no error, the file uploaded with success" => "エラーはありません。ファイルのアップロードは成功しました", +"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "アップロードされたファイルはphp.ini の upload_max_filesize に設定されたサイズを超えています:", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "アップロードファイルはHTMLフォームで指定された MAX_FILE_SIZE の制限を超えています", +"The uploaded file was only partially uploaded" => "アップロードファイルは一部分だけアップロードされました", +"No file was uploaded" => "ファイルはアップロードされませんでした", +"Missing a temporary folder" => "一時保存フォルダーが見つかりません", +"Failed to write to disk" => "ディスクへの書き込みに失敗しました", +"Not enough storage available" => "ストレージに十分な空き容量がありません", +"Upload failed. Could not find uploaded file" => "アップロードに失敗。アップロード済みのファイルを見つけることができませんでした。", +"Upload failed. Could not get file info." => "アップロードに失敗。ファイル情報を取得できませんでした。", +"Invalid directory." => "無効なディレクトリです。", +"Files" => "ファイル", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "ディレクトリもしくは0バイトのため {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." => "ファイル転送を実行中です。今このページから移動するとアップロードが中止されます。", +"URL cannot be empty" => "URL は空にできません", +"{new_name} already exists" => "{new_name} はすでに存在します", +"Could not create file" => "ファイルを作成できませんでした", +"Could not create folder" => "フォルダーを作成できませんでした", +"Error fetching URL" => "URL取得エラー", +"Share" => "共有", +"Delete permanently" => "完全に削除する", +"Rename" => "名前の変更", +"Your download is being prepared. This might take some time if the files are big." => "ダウンロードの準備中です。ファイルサイズが大きい場合は少し時間がかかるかもしれません。", +"Pending" => "中断", +"Error moving file." => "ファイル移動でエラー", +"Error moving file" => "ファイルの移動エラー", +"Error" => "エラー", +"Could not rename file" => "ファイルの名前変更ができませんでした", +"Error deleting file." => "ファイルの削除エラー。", +"Name" => "名前", +"Size" => "サイズ", +"Modified" => "更新日時", +"_%n folder_::_%n folders_" => array("%n 個のフォルダー"), +"_%n file_::_%n files_" => array("%n 個のファイル"), +"_Uploading %n file_::_Uploading %n files_" => array("%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." => "暗号化の機能は無効化されましたが、ファイルはすでに暗号化されています。個人設定からファイルを複合を行ってください。", +"{dirs} and {files}" => "{dirs} と {files}", +"%s could not be renamed" => "%sの名前を変更できませんでした", +"Upload (max. %s)" => "アップロード ( 最大 %s )", +"File handling" => "ファイル操作", +"Maximum upload size" => "最大アップロードサイズ", +"max. possible: " => "最大容量: ", +"Needed for multi-file and folder downloads." => "複数ファイルおよびフォルダーのダウンロードに必要", +"Enable ZIP-download" => "ZIP形式のダウンロードを有効にする", +"0 is unlimited" => "0を指定した場合は無制限", +"Maximum input size for ZIP files" => "ZIPファイルでの最大入力サイズ", +"Save" => "保存", +"New" => "新規作成", +"New text file" => "新規のテキストファイル作成", +"Text file" => "テキストファイル", +"New folder" => "新しいフォルダー", +"Folder" => "フォルダー", +"From link" => "リンク", +"Deleted files" => "ゴミ箱", +"Cancel upload" => "アップロードをキャンセル", +"You don’t have permission to upload or create files here" => "ここにファイルをアップロードもしくは作成する権限がありません", +"Nothing in here. Upload something!" => "ここには何もありません。何かアップロードしてください。", +"Download" => "ダウンロード", +"Delete" => "削除", +"Upload too large" => "アップロードには大きすぎます。", +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "アップロードしようとしているファイルは、サーバーで規定された最大サイズを超えています。", +"Files are being scanned, please wait." => "ファイルをスキャンしています、しばらくお待ちください。", +"Current scanning" => "スキャン中" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/ja_JP.php b/apps/files/l10n/ja_JP.php index 8019b825d3..8a4b3ca877 100644 --- a/apps/files/l10n/ja_JP.php +++ b/apps/files/l10n/ja_JP.php @@ -3,16 +3,17 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "%s を移動できませんでした ― この名前のファイルはすでに存在します", "Could not move %s" => "%s を移動できませんでした", "File name cannot be empty." => "ファイル名を空にすることはできません。", -"File name must not contain \"/\". Please choose a different name." => "ファイル名には \"/\" を含めることはできません。別の名前を選択してください。", -"The name %s is already used in the folder %s. Please choose a different name." => "%s はフォルダ %s ないですでに使われています。別の名前を選択してください。", +"\"%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を開くことは許されません。サーバーの設定をチェックしてください。", "Error while downloading %s to %s" => "%s から %s へのダウンロードエラー", "Error when creating the file" => "ファイルの生成エラー", -"Folder name cannot be empty." => "フォルダ名は空にできません", -"Folder name must not contain \"/\". Please choose a different name." => "フォルダ名には \"/\" を含めることはできません。別の名前を選択してください。", -"Error when creating the folder" => "フォルダの生成エラー", -"Unable to set upload directory." => "アップロードディレクトリを設定出来ません。", +"Folder name cannot be empty." => "フォルダー名は空にできません", +"Error when creating the folder" => "フォルダーの生成エラー", +"Unable to set upload directory." => "アップロードディレクトリを設定できません。", "Invalid Token" => "無効なトークン", "No file was uploaded. Unknown error" => "ファイルは何もアップロードされていません。不明なエラー", "There is no error, the file uploaded with success" => "エラーはありません。ファイルのアップロードは成功しました", @@ -20,23 +21,24 @@ $TRANSLATIONS = array( "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "アップロードファイルはHTMLフォームで指定された MAX_FILE_SIZE の制限を超えています", "The uploaded file was only partially uploaded" => "アップロードファイルは一部分だけアップロードされました", "No file was uploaded" => "ファイルはアップロードされませんでした", -"Missing a temporary folder" => "一時保存フォルダが見つかりません", +"Missing a temporary folder" => "一時保存フォルダーが見つかりません", "Failed to write to disk" => "ディスクへの書き込みに失敗しました", "Not enough storage available" => "ストレージに十分な空き容量がありません", -"Upload failed. Could not get file info." => "アップロードに失敗。ファイル情報を取得できませんでした。", "Upload failed. Could not find uploaded file" => "アップロードに失敗。アップロード済みのファイルを見つけることができませんでした。", +"Upload failed. Could not get file info." => "アップロードに失敗。ファイル情報を取得できませんでした。", "Invalid directory." => "無効なディレクトリです。", "Files" => "ファイル", "Unable to upload {filename} as it is a directory or has 0 bytes" => "ディレクトリもしくは0バイトのため {filename} をアップロードできません", -"Not enough space available" => "利用可能なスペースが十分にありません", +"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." => "サーバから結果を取得できませんでした。", +"Could not get result from server." => "サーバーから結果を取得できませんでした。", "File upload is in progress. Leaving the page now will cancel the upload." => "ファイル転送を実行中です。今このページから移動するとアップロードが中止されます。", "URL cannot be empty" => "URL は空にできません", -"In the home folder 'Shared' is a reserved filename" => "ホームフォルダでは、'Shared' はシステムが使用する予約済みのファイル名です", -"{new_name} already exists" => "{new_name} はすでに存在しています", +"In the home folder 'Shared' is a reserved filename" => "ホームフォルダーでは、'Shared' はシステムが使用する予約済みのファイル名です", +"{new_name} already exists" => "{new_name} はすでに存在します", "Could not create file" => "ファイルを作成できませんでした", -"Could not create folder" => "フォルダを作成できませんでした", +"Could not create folder" => "フォルダーを作成できませんでした", "Error fetching URL" => "URL取得エラー", "Share" => "共有", "Delete permanently" => "完全に削除する", @@ -46,14 +48,13 @@ $TRANSLATIONS = array( "replaced {new_name} with {old_name}" => "{old_name} を {new_name} に置換", "undo" => "元に戻す", "Error deleting file." => "ファイルの削除エラー。", -"_%n folder_::_%n folders_" => array("%n 個のフォルダ"), +"_%n folder_::_%n folders_" => array("%n 個のフォルダー"), "_%n file_::_%n files_" => array("%n 個のファイル"), "{dirs} and {files}" => "{dirs} と {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n 個のファイルをアップロード中"), -"'.' is an invalid file name." => "'.' は無効なファイル名です。", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "無効な名前、'\\', '/', '<', '>', ':', '\"', '|', '?', '*' は使用できません。", +"\"{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}%)", +"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." => "暗号化の機能は無効化されましたが、ファイルはすでに暗号化されています。個人設定からファイルを複合を行ってください。", @@ -63,22 +64,22 @@ $TRANSLATIONS = array( "Name" => "名前", "Size" => "サイズ", "Modified" => "更新日時", -"Invalid folder name. Usage of 'Shared' is reserved." => "無効なフォルダ名。「Shared」の利用は予約されています。", +"Invalid folder name. Usage of 'Shared' is reserved." => "無効なフォルダー名。「Shared」の利用は予約されています。", "%s could not be renamed" => "%sの名前を変更できませんでした", "Upload" => "アップロード", "File handling" => "ファイル操作", "Maximum upload size" => "最大アップロードサイズ", "max. possible: " => "最大容量: ", -"Needed for multi-file and folder downloads." => "複数ファイルおよびフォルダのダウンロードに必要", +"Needed for multi-file and folder downloads." => "複数ファイルおよびフォルダーのダウンロードに必要", "Enable ZIP-download" => "ZIP形式のダウンロードを有効にする", "0 is unlimited" => "0を指定した場合は無制限", -"Maximum input size for ZIP files" => "ZIPファイルへの最大入力サイズ", +"Maximum input size for ZIP files" => "ZIPファイルでの最大入力サイズ", "Save" => "保存", "New" => "新規作成", "New text file" => "新規のテキストファイル作成", "Text file" => "テキストファイル", -"New folder" => "新しいフォルダ", -"Folder" => "フォルダ", +"New folder" => "新しいフォルダー", +"Folder" => "フォルダー", "From link" => "リンク", "Deleted files" => "ゴミ箱", "Cancel upload" => "アップロードをキャンセル", @@ -87,7 +88,7 @@ $TRANSLATIONS = array( "Download" => "ダウンロード", "Delete" => "削除", "Upload too large" => "アップロードには大きすぎます。", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "アップロードしようとしているファイルは、サーバで規定された最大サイズを超えています。", +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "アップロードしようとしているファイルは、サーバーで規定された最大サイズを超えています。", "Files are being scanned, please wait." => "ファイルをスキャンしています、しばらくお待ちください。", "Current scanning" => "スキャン中", "Upgrading filesystem cache..." => "ファイルシステムキャッシュを更新中..." diff --git a/apps/files/l10n/jv.php b/apps/files/l10n/jv.php new file mode 100644 index 0000000000..cfab5af7d1 --- /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 eafa0c083f..d9f5244fa7 100644 --- a/apps/files/l10n/ka_GE.php +++ b/apps/files/l10n/ka_GE.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "%s –ის გადატანა ვერ მოხერხდა – ფაილი ამ სახელით უკვე არსებობს", "Could not move %s" => "%s –ის გადატანა ვერ მოხერხდა", "File name cannot be empty." => "ფაილის სახელი არ შეიძლება იყოს ცარიელი.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "არადაშვებადი სახელი, '\\', '/', '<', '>', ':', '\"', '|', '?' და '*' არ არის დაიშვებული.", "No file was uploaded. Unknown error" => "ფაილი არ აიტვირთა. უცნობი შეცდომა", "There is no error, the file uploaded with success" => "ჭოცდომა არ დაფიქსირდა, ფაილი წარმატებით აიტვირთა", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "ატვირთული ფაილი აჭარბებს upload_max_filesize დირექტივას php.ini ფაილში", @@ -14,29 +15,23 @@ $TRANSLATIONS = array( "Not enough storage available" => "საცავში საკმარისი ადგილი არ არის", "Invalid directory." => "დაუშვებელი დირექტორია.", "Files" => "ფაილები", -"Not enough space available" => "საკმარისი ადგილი არ არის", "Upload cancelled." => "ატვირთვა შეჩერებულ იქნა.", "File upload is in progress. Leaving the page now will cancel the upload." => "მიმდინარეობს ფაილის ატვირთვა. სხვა გვერდზე გადასვლა გამოიწვევს ატვირთვის შეჩერებას", "{new_name} already exists" => "{new_name} უკვე არსებობს", "Share" => "გაზიარება", "Delete permanently" => "სრულად წაშლა", "Rename" => "გადარქმევა", -"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(""), -"'.' is an invalid file name." => "'.' არის დაუშვებელი ფაილის სახელი.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "არადაშვებადი სახელი, '\\', '/', '<', '>', ':', '\"', '|', '?' და '*' არ არის დაიშვებული.", -"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." => "გადმოწერის მოთხოვნა მუშავდება. ის მოითხოვს გარკვეულ დროს რაგდან ფაილები არის დიდი ზომის.", +"Pending" => "მოცდის რეჟიმში", "Error" => "შეცდომა", "Name" => "სახელი", "Size" => "ზომა", "Modified" => "შეცვლილია", -"Upload" => "ატვირთვა", +"_%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}%)", "File handling" => "ფაილის დამუშავება", "Maximum upload size" => "მაქსიმუმ ატვირთის ზომა", "max. possible: " => "მაქს. შესაძლებელი:", @@ -58,7 +53,6 @@ $TRANSLATIONS = array( "Upload too large" => "ასატვირთი ფაილი ძალიან დიდია", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "ფაილის ზომა რომლის ატვირთვასაც თქვენ აპირებთ, აჭარბებს სერვერზე დაშვებულ მაქსიმუმს.", "Files are being scanned, please wait." => "მიმდინარეობს ფაილების სკანირება, გთხოვთ დაელოდოთ.", -"Current scanning" => "მიმდინარე სკანირება", -"Upgrading filesystem cache..." => "ფაილური სისტემის ქეშის განახლება...." +"Current scanning" => "მიმდინარე სკანირება" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/km.php b/apps/files/l10n/km.php index 9733358d62..08b29304c1 100644 --- a/apps/files/l10n/km.php +++ b/apps/files/l10n/km.php @@ -1,8 +1,17 @@ "ឯកសារ", +"Share" => "ចែក​រំលែក", +"Error" => "កំហុស", +"Name" => "ឈ្មោះ", +"Size" => "ទំហំ", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), +"Save" => "រក្សាទុក", +"New folder" => "ថត​ថ្មី", +"Folder" => "ថត", +"Download" => "ទាញយក", "Delete" => "លុប" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/ko.php b/apps/files/l10n/ko.php index 35a9f2fb85..bfb69bb444 100644 --- a/apps/files/l10n/ko.php +++ b/apps/files/l10n/ko.php @@ -3,14 +3,13 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "항목 %s을(를) 이동시킬 수 없음 - 같은 이름의 파일이 이미 존재함", "Could not move %s" => "항목 %s을(를) 이동시킬 수 없음", "File name cannot be empty." => "파일 이름이 비어 있을 수 없습니다.", -"File name must not contain \"/\". Please choose a different name." => "파일 이름에는 \"/\"가 들어갈 수 없습니다. 다른 이름을 사용하십시오.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "폴더 이름이 올바르지 않습니다. 이름에 문자 '\\', '/', '<', '>', ':', '\"', '|', '? ', '*'는 사용할 수 없습니다.", "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을 열 수 없습니다. 서버 설정을 확인하십시오", "Error while downloading %s to %s" => "%s을(를) %s(으)로 다운로드하는 중 오류 발생", "Error when creating the file" => "파일 생성 중 오류 발생", "Folder name cannot be empty." => "폴더 이름이 비어있을 수 없습니다.", -"Folder name must not contain \"/\". Please choose a different name." => "폴더 이름에는 \"/\"가 들어갈 수 없습니다. 다른 이름을 사용하십시오.", "Error when creating the folder" => "폴더 생성 중 오류 발생", "Unable to set upload directory." => "업로드 디렉터리를 설정할 수 없습니다.", "Invalid Token" => "잘못된 토큰", @@ -23,17 +22,15 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "임시 폴더가 없음", "Failed to write to disk" => "디스크에 쓰지 못했습니다", "Not enough storage available" => "저장소가 용량이 충분하지 않습니다.", -"Upload failed. Could not get file info." => "업로드에 실패했습니다. 파일 정보를 가져올 수 없습니다.", "Upload failed. Could not find uploaded file" => "업로드에 실패했습니다. 업로드할 파일을 찾을 수 없습니다", +"Upload failed. Could not get file info." => "업로드에 실패했습니다. 파일 정보를 가져올 수 없습니다.", "Invalid directory." => "올바르지 않은 디렉터리입니다.", "Files" => "파일", "Unable to upload {filename} as it is a directory or has 0 bytes" => "{filename}을(를) 업로드할 수 없습니다. 폴더이거나 0 바이트 파일입니다.", -"Not enough space available" => "여유 공간이 부족합니다", "Upload cancelled." => "업로드가 취소되었습니다.", "Could not get result from server." => "서버에서 결과를 가져올 수 없습니다.", "File upload is in progress. Leaving the page now will cancel the upload." => "파일 업로드가 진행 중입니다. 이 페이지를 벗어나면 업로드가 취소됩니다.", "URL cannot be empty" => "URL이 비어있을 수 없음", -"In the home folder 'Shared' is a reserved filename" => "'공유됨'은 홈 폴더의 예약된 파일 이름임", "{new_name} already exists" => "{new_name}이(가) 이미 존재함", "Could not create file" => "파일을 만들 수 없음", "Could not create folder" => "폴더를 만들 수 없음", @@ -41,31 +38,25 @@ $TRANSLATIONS = array( "Share" => "공유", "Delete permanently" => "영구히 삭제", "Rename" => "이름 바꾸기", +"Your download is being prepared. This might take some time if the files are big." => "다운로드 준비 중입니다. 파일 크기가 크면 시간이 오래 걸릴 수도 있습니다.", "Pending" => "대기 중", +"Error moving file" => "파일 이동 오류", +"Error" => "오류", "Could not rename file" => "이름을 변경할 수 없음", -"replaced {new_name} with {old_name}" => "{old_name}이(가) {new_name}(으)로 대체됨", -"undo" => "실행 취소", "Error deleting file." => "파일 삭제 오류.", +"Name" => "이름", +"Size" => "크기", +"Modified" => "수정됨", "_%n folder_::_%n folders_" => array("폴더 %n개"), "_%n file_::_%n files_" => array("파일 %n개"), -"{dirs} and {files}" => "{dirs} 그리고 {files}", "_Uploading %n file_::_Uploading %n files_" => array("파일 %n개 업로드 중"), -"'.' is an invalid file name." => "'.' 는 올바르지 않은 파일 이름입니다.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "폴더 이름이 올바르지 않습니다. 이름에 문자 '\\', '/', '<', '>', ':', '\"', '|', '? ', '*'는 사용할 수 없습니다.", "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" => "수정됨", -"Invalid folder name. Usage of 'Shared' is reserved." => "폴더 이름이 잘못되었습니다. '공유됨'은 예약된 폴더 이름입니다.", +"{dirs} and {files}" => "{dirs} 그리고 {files}", "%s could not be renamed" => "%s의 이름을 변경할 수 없습니다", -"Upload" => "업로드", "File handling" => "파일 처리", "Maximum upload size" => "최대 업로드 크기", "max. possible: " => "최대 가능:", @@ -89,7 +80,6 @@ $TRANSLATIONS = array( "Upload too large" => "업로드한 파일이 너무 큼", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "이 파일이 서버에서 허용하는 최대 업로드 가능 용량보다 큽니다.", "Files are being scanned, please wait." => "파일을 검색하고 있습니다. 기다려 주십시오.", -"Current scanning" => "현재 검색", -"Upgrading filesystem cache..." => "파일 시스템 캐시 업그레이드 중..." +"Current scanning" => "현재 검색" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/ku_IQ.php b/apps/files/l10n/ku_IQ.php index f04e9ec44d..4afe5e4cc2 100644 --- a/apps/files/l10n/ku_IQ.php +++ b/apps/files/l10n/ku_IQ.php @@ -1,12 +1,12 @@ "په‌ڕگەکان", "Share" => "هاوبەشی کردن", +"Error" => "هه‌ڵه", +"Name" => "ناو", "_%n folder_::_%n folders_" => array("",""), "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), -"Error" => "هه‌ڵه", -"Name" => "ناو", -"Upload" => "بارکردن", "Save" => "پاشکه‌وتکردن", "Folder" => "بوخچه", "Download" => "داگرتن" diff --git a/apps/files/l10n/lb.php b/apps/files/l10n/lb.php index 822ca7e2d0..b742be43c3 100644 --- a/apps/files/l10n/lb.php +++ b/apps/files/l10n/lb.php @@ -11,15 +11,13 @@ $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", -"_%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", -"Upload" => "Eroplueden", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "File handling" => "Fichier handling", "Maximum upload size" => "Maximum Upload Gréisst ", "max. possible: " => "max. méiglech:", diff --git a/apps/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php index d902365863..b2055162d9 100644 --- a/apps/files/l10n/lt_LT.php +++ b/apps/files/l10n/lt_LT.php @@ -3,13 +3,13 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Nepavyko perkelti %s - failas su tokiu pavadinimu jau egzistuoja", "Could not move %s" => "Nepavyko perkelti %s", "File name cannot be empty." => "Failo pavadinimas negali būti tuščias.", -"File name must not contain \"/\". Please choose a different name." => "Failo pavadinime negali būti simbolio \"/\". Prašome pasirinkti kitokį pavadinimą.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neleistinas pavadinimas, '\\', '/', '<', '>', ':', '\"', '|', '?' ir '*' yra neleidžiami.", "The name %s is already used in the folder %s. Please choose a different name." => "Pavadinimas %s jau naudojamas aplanke %s. Prašome pasirinkti kitokį pavadinimą.", "Not a valid source" => "Netinkamas šaltinis", +"Server is not allowed to open URLs, please check the server configuration" => "Serveriui neleidžiama atverti URL, prašome patikrinti serverio konfigūraciją", "Error while downloading %s to %s" => "Klaida siunčiant %s į %s", "Error when creating the file" => "Klaida kuriant failą", "Folder name cannot be empty." => "Aplanko pavadinimas negali būti tuščias.", -"Folder name must not contain \"/\". Please choose a different name." => "Aplanko pavadinime negali būti simbolio \"/\". Prašome pasirinkti kitokį pavadinimą.", "Error when creating the folder" => "Klaida kuriant aplanką", "Unable to set upload directory." => "Nepavyksta nustatyti įkėlimų katalogo.", "Invalid Token" => "Netinkamas ženklas", @@ -22,12 +22,11 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Nėra laikinojo katalogo", "Failed to write to disk" => "Nepavyko įrašyti į diską", "Not enough storage available" => "Nepakanka vietos serveryje", -"Upload failed. Could not get file info." => "Įkėlimas nepavyko. Nepavyko gauti failo informacijos.", "Upload failed. Could not find uploaded file" => "Įkėlimas nepavyko. Nepavyko rasti įkelto failo", +"Upload failed. Could not get file info." => "Įkėlimas nepavyko. Nepavyko gauti failo informacijos.", "Invalid directory." => "Neteisingas aplankas", "Files" => "Failai", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Nepavyksta įkelti {filename}, nes tai katalogas arba yra 0 baitų dydžio", -"Not enough space available" => "Nepakanka vietos", "Upload cancelled." => "Įkėlimas atšauktas.", "Could not get result from server." => "Nepavyko gauti rezultato iš serverio.", "File upload is in progress. Leaving the page now will cancel the upload." => "Failo įkėlimas pradėtas. Jei paliksite šį puslapį, įkėlimas nutrūks.", @@ -35,33 +34,29 @@ $TRANSLATIONS = array( "{new_name} already exists" => "{new_name} jau egzistuoja", "Could not create file" => "Neįmanoma sukurti failo", "Could not create folder" => "Neįmanoma sukurti aplanko", +"Error fetching URL" => "Klauda gaunant URL", "Share" => "Dalintis", "Delete permanently" => "Ištrinti negrįžtamai", "Rename" => "Pervadinti", +"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.", "Pending" => "Laukiantis", +"Error moving file" => "Klaida perkeliant failą", +"Error" => "Klaida", "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ą.", +"Name" => "Pavadinimas", +"Size" => "Dydis", +"Modified" => "Pakeista", "_%n folder_::_%n folders_" => array("%n aplankas","%n aplankai","%n aplankų"), "_%n file_::_%n files_" => array("%n failas","%n failai","%n failų"), -"{dirs} and {files}" => "{dirs} ir {files}", "_Uploading %n file_::_Uploading %n files_" => array("Įkeliamas %n failas","Įkeliami %n failai","Įkeliama %n failų"), -"'.' is an invalid file name." => "'.' yra neleidžiamas failo pavadinime.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neleistinas pavadinimas, '\\', '/', '<', '>', ':', '\"', '|', '?' ir '*' yra neleidžiami.", "Your storage is full, files can not be updated or synced anymore!" => "Jūsų visa vieta serveryje užimta", "Your storage is almost full ({usedSpacePercent}%)" => "Jūsų vieta serveryje beveik visa užimta ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Šifravimo programa įjungta, bet Jūsų raktai nėra pritaikyti. Prašome atsijungti ir vėl prisijungti", "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", +"{dirs} and {files}" => "{dirs} ir {files}", "%s could not be renamed" => "%s negali būti pervadintas", -"Upload" => "Įkelti", "File handling" => "Failų tvarkymas", "Maximum upload size" => "Maksimalus įkeliamo failo dydis", "max. possible: " => "maks. galima:", @@ -71,6 +66,7 @@ $TRANSLATIONS = array( "Maximum input size for ZIP files" => "Maksimalus ZIP archyvo failo dydis", "Save" => "Išsaugoti", "New" => "Naujas", +"New text file" => "Naujas tekstinis failas", "Text file" => "Teksto failas", "New folder" => "Naujas aplankas", "Folder" => "Katalogas", @@ -84,7 +80,6 @@ $TRANSLATIONS = array( "Upload too large" => "Įkėlimui failas per didelis", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Bandomų įkelti failų dydis viršija maksimalų, kuris leidžiamas šiame serveryje", "Files are being scanned, please wait." => "Skenuojami failai, prašome palaukti.", -"Current scanning" => "Šiuo metu skenuojama", -"Upgrading filesystem cache..." => "Atnaujinamas sistemos kešavimas..." +"Current scanning" => "Šiuo metu skenuojama" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/files/l10n/lv.php b/apps/files/l10n/lv.php index 7f8975b294..c5a9b9338a 100644 --- a/apps/files/l10n/lv.php +++ b/apps/files/l10n/lv.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Nevarēja pārvietot %s — jau eksistē datne ar tādu nosaukumu", "Could not move %s" => "Nevarēja pārvietot %s", "File name cannot be empty." => "Datnes nosaukums nevar būt tukšs.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nederīgs nosaukums, nav atļauti '\\', '/', '<', '>', ':', '\"', '|', '?' un '*'.", "Unable to set upload directory." => "Nevar uzstādīt augšupielādes mapi.", "Invalid Token" => "Nepareiza pilnvara", "No file was uploaded. Unknown error" => "Netika augšupielādēta neviena datne. Nezināma kļūda", @@ -16,31 +17,25 @@ $TRANSLATIONS = array( "Not enough storage available" => "Nav pietiekami daudz vietas", "Invalid directory." => "Nederīga direktorija.", "Files" => "Datnes", -"Not enough space available" => "Nepietiek brīvas vietas", "Upload cancelled." => "Augšupielāde ir atcelta.", "File upload is in progress. Leaving the page now will cancel the upload." => "Notiek augšupielāde. Pametot lapu tagad, tiks atcelta augšupielāde.", "{new_name} already exists" => "{new_name} jau eksistē", "Share" => "Dalīties", "Delete permanently" => "Dzēst pavisam", "Rename" => "Pārsaukt", -"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"), -"'.' is an invalid file name." => "'.' ir nederīgs datnes nosaukums.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nederīgs nosaukums, nav atļauti '\\', '/', '<', '>', ':', '\"', '|', '?' un '*'.", -"Your storage is full, files can not be updated or synced anymore!" => "Jūsu krātuve ir pilna, datnes vairs nevar augšupielādēt vai sinhronizēt!", -"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.", +"Pending" => "Gaida savu kārtu", "Error" => "Kļūda", "Name" => "Nosaukums", "Size" => "Izmērs", "Modified" => "Mainīts", +"_%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"), +"Your storage is full, files can not be updated or synced anymore!" => "Jūsu krātuve ir pilna, datnes vairs nevar augšupielādēt vai sinhronizēt!", +"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.", "%s could not be renamed" => "%s nevar tikt pārsaukts", -"Upload" => "Augšupielādēt", "File handling" => "Datņu pārvaldība", "Maximum upload size" => "Maksimālais datņu augšupielādes apjoms", "max. possible: " => "maksimālais iespējamais:", @@ -62,7 +57,6 @@ $TRANSLATIONS = array( "Upload too large" => "Datne ir par lielu, lai to augšupielādētu", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Augšupielādējamās datnes pārsniedz servera pieļaujamo datņu augšupielādes apjomu", "Files are being scanned, please wait." => "Datnes šobrīd tiek caurskatītas, lūdzu, uzgaidiet.", -"Current scanning" => "Šobrīd tiek caurskatīts", -"Upgrading filesystem cache..." => "Uzlabo datņu sistēmas kešatmiņu..." +"Current scanning" => "Šobrīd tiek caurskatīts" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"; diff --git a/apps/files/l10n/mk.php b/apps/files/l10n/mk.php index fadf5efc07..4a1f16c792 100644 --- a/apps/files/l10n/mk.php +++ b/apps/files/l10n/mk.php @@ -3,11 +3,11 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Не можам да го преместам %s - Датотека со такво име веќе постои", "Could not move %s" => "Не можам да ги префрлам %s", "File name cannot be empty." => "Името на датотеката не може да биде празно.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неправилно име. , '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' не се дозволени.", "Not a valid source" => "Не е валиден извор", "Error while downloading %s to %s" => "Грешка додека преземам %s to %s", "Error when creating the file" => "Грешка при креирање на датотека", "Folder name cannot be empty." => "Името на папката не може да биде празно.", -"Folder name must not contain \"/\". Please choose a different name." => "Името на папката не смее да содржи \"/\". Одберете друго име.", "Error when creating the folder" => "Грешка при креирање на папка", "Unable to set upload directory." => "Не може да се постави папката за префрлање на податоци.", "Invalid Token" => "Грешен токен", @@ -23,38 +23,31 @@ $TRANSLATIONS = array( "Upload failed. Could not find uploaded file" => "Префрлањето е неуспешно. Не можам да го најдам префрлената датотека.", "Invalid directory." => "Погрешна папка.", "Files" => "Датотеки", -"Not enough space available" => "Немате доволно дисков простор", "Upload cancelled." => "Преземањето е прекинато.", "Could not get result from server." => "Не можам да добијам резултат од серверот.", "File upload is in progress. Leaving the page now will cancel the upload." => "Подигање на датотека е во тек. Напуштење на страницата ќе го прекине.", "URL cannot be empty" => "URL-то не може да биде празно", -"In the home folder 'Shared' is a reserved filename" => "Во домашната папка, 'Shared' е резервирано има на датотека/папка", "{new_name} already exists" => "{new_name} веќе постои", "Could not create file" => "Не множам да креирам датотека", "Could not create folder" => "Не можам да креирам папка", "Share" => "Сподели", "Delete permanently" => "Трајно избришани", "Rename" => "Преименувај", -"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}", -"_Uploading %n file_::_Uploading %n files_" => array("",""), -"'.' is an invalid file name." => "'.' е грешно име за датотека.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неправилно име. , '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' не се дозволени.", -"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." => "Вашето преземање се подготвува. Ова може да потрае до колку датотеките се големи.", +"Pending" => "Чека", "Error moving file" => "Грешка при префрлање на датотека", "Error" => "Грешка", +"Could not rename file" => "Не можам да ја преименувам датотеката", "Name" => "Име", "Size" => "Големина", "Modified" => "Променето", +"_%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}%)", +"{dirs} and {files}" => "{dirs} и {files}", "%s could not be renamed" => "%s не може да биде преименуван", -"Upload" => "Подигни", "File handling" => "Ракување со датотеки", "Maximum upload size" => "Максимална големина за подигање", "max. possible: " => "макс. можно:", @@ -75,7 +68,6 @@ $TRANSLATIONS = array( "Upload too large" => "Фајлот кој се вчитува е преголем", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Датотеките кои се обидувате да ги подигнете ја надминуваат максималната големина за подигнување датотеки на овој сервер.", "Files are being scanned, please wait." => "Се скенираат датотеки, ве молам почекајте.", -"Current scanning" => "Моментално скенирам", -"Upgrading filesystem cache..." => "Го надградувам кешот на фјал системот..." +"Current scanning" => "Моментално скенирам" ); $PLURAL_FORMS = "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"; diff --git a/apps/files/l10n/ml.php b/apps/files/l10n/ml.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/ml.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/mn.php b/apps/files/l10n/mn.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/mn.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ms_MY.php b/apps/files/l10n/ms_MY.php index 0a7a50abb1..81d3de6299 100644 --- a/apps/files/l10n/ms_MY.php +++ b/apps/files/l10n/ms_MY.php @@ -12,14 +12,13 @@ $TRANSLATIONS = array( "Share" => "Kongsi", "Rename" => "Namakan", "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", -"Upload" => "Muat naik", +"_%n folder_::_%n folders_" => array(""), +"_%n file_::_%n files_" => array(""), +"_Uploading %n file_::_Uploading %n files_" => array(""), "File handling" => "Pengendalian fail", "Maximum upload size" => "Saiz maksimum muat naik", "max. possible: " => "maksimum:", diff --git a/apps/files/l10n/nb_NO.php b/apps/files/l10n/nb_NO.php index ebd7ef3899..80b706dd53 100644 --- a/apps/files/l10n/nb_NO.php +++ b/apps/files/l10n/nb_NO.php @@ -3,6 +3,14 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Kan ikke flytte %s - En fil med samme navn finnes allerede", "Could not move %s" => "Kunne ikke flytte %s", "File name cannot be empty." => "Filnavn kan ikke være tomt.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig navn, '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' er ikke tillatt.", +"The name %s is already used in the folder %s. Please choose a different name." => "Navnet %s brukes allerede i mappen %s. Velg et annet navn.", +"Not a valid source" => "Ikke en gyldig kilde", +"Server is not allowed to open URLs, please check the server configuration" => "Serveren har ikke lov til å åpne URL-er. Sjekk konfigurasjon av server", +"Error while downloading %s to %s" => "Feil ved nedlasting av %s til %s", +"Error when creating the file" => "Feil ved oppretting av filen", +"Folder name cannot be empty." => "Mappenavn kan ikke være tomt.", +"Error when creating the folder" => "Feil ved oppretting av mappen", "Unable to set upload directory." => "Kunne ikke sette opplastingskatalog.", "Invalid Token" => "Ugyldig nøkkel", "No file was uploaded. Unknown error" => "Ingen filer ble lastet opp. Ukjent feil.", @@ -14,32 +22,41 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Mangler midlertidig mappe", "Failed to write to disk" => "Klarte ikke å skrive til disk", "Not enough storage available" => "Ikke nok lagringsplass", +"Upload failed. Could not find uploaded file" => "Opplasting feilet. Fant ikke opplastet fil.", +"Upload failed. Could not get file info." => "Opplasting feilet. Klarte ikke å finne informasjon om fil.", "Invalid directory." => "Ugyldig katalog.", "Files" => "Filer", -"Not enough space available" => "Ikke nok lagringsplass", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "Kan ikke laste opp {filename} fordi det er en mappe eller har 0 bytes", "Upload cancelled." => "Opplasting avbrutt.", +"Could not get result from server." => "Fikk ikke resultat fra serveren.", "File upload is in progress. Leaving the page now will cancel the upload." => "Filopplasting pågår. Forlater du siden nå avbrytes opplastingen.", +"URL cannot be empty" => "URL kan ikke være tom", "{new_name} already exists" => "{new_name} finnes allerede", +"Could not create file" => "Klarte ikke å opprette fil", +"Could not create folder" => "Klarte ikke å opprette mappe", +"Error fetching URL" => "Feil ved henting av URL", "Share" => "Del", "Delete permanently" => "Slett permanent", "Rename" => "Gi nytt navn", -"Pending" => "Ventende", -"replaced {new_name} with {old_name}" => "erstattet {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"), -"_Uploading %n file_::_Uploading %n files_" => array("Laster opp %n fil","Laster opp %n filer"), -"'.' is an invalid file name." => "'.' er et ugyldig filnavn.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig navn, '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' er ikke tillatt.", -"Your storage is full, files can not be updated or synced anymore!" => "Lagringsplass er oppbrukt, filer kan ikke lenger oppdateres eller synkroniseres!", -"Your storage is almost full ({usedSpacePercent}%)" => "Lagringsplass er nesten brukt opp ([usedSpacePercent}%)", "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.", +"Pending" => "Ventende", +"Error moving file" => "Feil ved flytting av fil", "Error" => "Feil", +"Could not rename file" => "Klarte ikke å gi nytt navn til fil", +"Error deleting file." => "Feil ved sletting av fil.", "Name" => "Navn", "Size" => "Størrelse", "Modified" => "Endret", +"_%n folder_::_%n folders_" => array("%n mappe","%n mapper"), +"_%n file_::_%n files_" => array("%n fil","%n filer"), +"_Uploading %n file_::_Uploading %n files_" => array("Laster opp %n fil","Laster opp %n filer"), +"Your storage is full, files can not be updated or synced anymore!" => "Lagringsplass er oppbrukt, filer kan ikke lenger oppdateres eller synkroniseres!", +"Your storage is almost full ({usedSpacePercent}%)" => "Lagringsplass er nesten brukt opp ([usedSpacePercent}%)", +"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "App for kryptering er aktivert men nøklene dine er ikke satt opp. Logg ut og logg inn igjen.", +"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.", +"{dirs} and {files}" => "{dirs} og {files}", "%s could not be renamed" => "Kunne ikke gi nytt navn til %s", -"Upload" => "Last opp", "File handling" => "Filhåndtering", "Maximum upload size" => "Maksimum opplastingsstørrelse", "max. possible: " => "max. mulige:", @@ -49,19 +66,20 @@ $TRANSLATIONS = array( "Maximum input size for ZIP files" => "Maksimal størrelse på ZIP-filer", "Save" => "Lagre", "New" => "Ny", +"New text file" => "Ny tekstfil", "Text file" => "Tekstfil", "New folder" => "Ny mappe", "Folder" => "Mappe", "From link" => "Fra link", -"Deleted files" => "Slettet filer", +"Deleted files" => "Slettede filer", "Cancel upload" => "Avbryt opplasting", +"You don’t have permission to upload or create files here" => "Du har ikke tillatelse til å laste opp eller opprette filer her", "Nothing in here. Upload something!" => "Ingenting her. Last opp noe!", "Download" => "Last ned", "Delete" => "Slett", "Upload too large" => "Filen er for stor", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filene du prøver å laste opp er for store for å laste opp til denne serveren.", "Files are being scanned, please wait." => "Skanner filer, vennligst vent.", -"Current scanning" => "Pågående skanning", -"Upgrading filesystem cache..." => "Oppgraderer filsystemets mellomlager..." +"Current scanning" => "Pågående skanning" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/nl.php b/apps/files/l10n/nl.php index a391e25b95..6bde1e612d 100644 --- a/apps/files/l10n/nl.php +++ b/apps/files/l10n/nl.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Kon %s niet verplaatsen - Er bestaat al een bestand met deze naam", "Could not move %s" => "Kon %s niet verplaatsen", "File name cannot be empty." => "Bestandsnaam kan niet leeg zijn.", -"File name must not contain \"/\". Please choose a different name." => "De bestandsnaam mag geen \"/\" bevatten. Kies een andere naam.", +"\"%s\" is an invalid file name." => "\"%s\" is een ongeldige bestandsnaam.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Onjuiste naam; '\\', '/', '<', '>', ':', '\"', '|', '?' en '*' zijn niet toegestaan.", +"The target folder has been moved or deleted." => "De doelmap is verplaatst of verwijderd.", "The name %s is already used in the folder %s. Please choose a different name." => "De naam %s bestaat al in map %s. Kies een andere naam.", "Not a valid source" => "Geen geldige bron", "Server is not allowed to open URLs, please check the server configuration" => "Server mag geen URS's openen, controleer de server configuratie", "Error while downloading %s to %s" => "Fout bij downloaden %s naar %s", "Error when creating the file" => "Fout bij creëren bestand", "Folder name cannot be empty." => "Mapnaam mag niet leeg zijn.", -"Folder name must not contain \"/\". Please choose a different name." => "De mapnaam mag geen \"/\" bevatten. Kies een andere naam.", "Error when creating the folder" => "Fout bij aanmaken map", "Unable to set upload directory." => "Kan upload map niet instellen.", "Invalid Token" => "Ongeldig Token", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Er ontbreekt een tijdelijke map", "Failed to write to disk" => "Schrijven naar schijf mislukt", "Not enough storage available" => "Niet genoeg opslagruimte beschikbaar", -"Upload failed. Could not get file info." => "Upload mislukt, Kon geen bestandsinfo krijgen.", "Upload failed. Could not find uploaded file" => "Upload mislukt. Kon ge-uploade bestand niet vinden", +"Upload failed. Could not get file info." => "Upload mislukt, Kon geen bestandsinfo krijgen.", "Invalid directory." => "Ongeldige directory.", "Files" => "Bestanden", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Kan {filename} niet uploaden omdat het een map is of 0 bytes groot is", -"Not enough space available" => "Niet genoeg ruimte beschikbaar", +"Total file size {size1} exceeds upload limit {size2}" => "Totale bestandsgrootte {size1} groter dan uploadlimiet {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Niet genoeg vrije ruimte. U upload {size1}, maar is is slechts {size2} beschikbaar", "Upload cancelled." => "Uploaden geannuleerd.", "Could not get result from server." => "Kon het resultaat van de server niet terugkrijgen.", "File upload is in progress. Leaving the page now will cancel the upload." => "Bestandsupload is bezig. Wanneer de pagina nu verlaten wordt, stopt de upload.", "URL cannot be empty" => "URL mag niet leeg zijn", -"In the home folder 'Shared' is a reserved filename" => "in de home map 'Shared' is een gereserveerde bestandsnaam", "{new_name} already exists" => "{new_name} bestaat al", "Could not create file" => "Kon bestand niet creëren", "Could not create folder" => "Kon niet creëren map", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Delen", "Delete permanently" => "Verwijder definitief", "Rename" => "Hernoem", +"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.", "Pending" => "In behandeling", +"Error moving file." => "Fout bij verplaatsen bestand", +"Error moving file" => "Fout bij verplaatsen bestand", +"Error" => "Fout", "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.", +"Name" => "Naam", +"Size" => "Grootte", +"Modified" => "Aangepast", "_%n folder_::_%n folders_" => array("","%n mappen"), "_%n file_::_%n files_" => array("","%n bestanden"), -"{dirs} and {files}" => "{dirs} en {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n bestand aan het uploaden","%n bestanden aan het uploaden"), -"'.' is an invalid file name." => "'.' is een ongeldige bestandsnaam.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Onjuiste naam; '\\', '/', '<', '>', ':', '\"', '|', '?' en '*' zijn niet toegestaan.", +"\"{name}\" is an invalid file name." => "\"{name}\" is een ongeldige bestandsnaam.", "Your storage is full, files can not be updated or synced anymore!" => "Uw opslagruimte zit vol, Bestanden kunnen niet meer worden ge-upload of gesynchroniseerd!", "Your storage is almost full ({usedSpacePercent}%)" => "Uw opslagruimte zit bijna vol ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Crypto app is geactiveerd, maar uw sleutels werden niet geïnitialiseerd. Log uit en log daarna opnieuw in.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Ongeldige mapnaam. Gebruik van 'Shared' is gereserveerd.", +"{dirs} and {files}" => "{dirs} en {files}", "%s could not be renamed" => "%s kon niet worden hernoemd", -"Upload" => "Uploaden", +"Upload (max. %s)" => "Upload (max. %s)", "File handling" => "Bestand", "Maximum upload size" => "Maximale bestandsgrootte voor uploads", "max. possible: " => "max. mogelijk: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Upload is te groot", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "De bestanden die u probeert te uploaden zijn groter dan de maximaal toegestane bestandsgrootte voor deze server.", "Files are being scanned, please wait." => "Bestanden worden gescand, even wachten.", -"Current scanning" => "Er wordt gescand", -"Upgrading filesystem cache..." => "Upgraden bestandssysteem cache..." +"Current scanning" => "Er wordt gescand" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/nn_NO.php b/apps/files/l10n/nn_NO.php index a5e6e737ea..238d1459b1 100644 --- a/apps/files/l10n/nn_NO.php +++ b/apps/files/l10n/nn_NO.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Klarte ikkje flytta %s – det finst allereie ei fil med dette namnet", "Could not move %s" => "Klarte ikkje flytta %s", "File name cannot be empty." => "Filnamnet kan ikkje vera tomt.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig namn, «\\», «/», «<», «>», «:», «\"», «|», «?» og «*» er ikkje tillate.", "Unable to set upload directory." => "Klarte ikkje å endra opplastingsmappa.", "Invalid Token" => "Ugyldig token", "No file was uploaded. Unknown error" => "Ingen filer lasta opp. Ukjend feil", @@ -14,12 +15,11 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Manglar ei mellombels mappe", "Failed to write to disk" => "Klarte ikkje skriva til disk", "Not enough storage available" => "Ikkje nok lagringsplass tilgjengeleg", -"Upload failed. Could not get file info." => "Feil ved opplasting. Klarte ikkje å henta filinfo.", "Upload failed. Could not find uploaded file" => "Feil ved opplasting. Klarte ikkje å finna opplasta fil.", +"Upload failed. Could not get file info." => "Feil ved opplasting. Klarte ikkje å henta filinfo.", "Invalid directory." => "Ugyldig mappe.", "Files" => "Filer", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Klarte ikkje å lasta opp {filename} sidan det er ei mappe eller er 0 byte.", -"Not enough space available" => "Ikkje nok lagringsplass tilgjengeleg", "Upload cancelled." => "Opplasting avbroten.", "Could not get result from server." => "Klarte ikkje å henta resultat frå tenaren.", "File upload is in progress. Leaving the page now will cancel the upload." => "Fila lastar no opp. Viss du forlèt sida no vil opplastinga verta avbroten.", @@ -27,26 +27,21 @@ $TRANSLATIONS = array( "Share" => "Del", "Delete permanently" => "Slett for godt", "Rename" => "Endra namn", -"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}", -"_Uploading %n file_::_Uploading %n files_" => array("Lastar opp %n fil","Lastar opp %n filer"), -"'.' is an invalid file name." => "«.» er eit ugyldig filnamn.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig namn, «\\», «/», «<», «>», «:», «\"», «|», «?» og «*» er ikkje tillate.", -"Your storage is full, files can not be updated or synced anymore!" => "Lagringa di er full, kan ikkje lenger oppdatera eller synkronisera!", -"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.", +"Pending" => "Under vegs", "Error moving file" => "Feil ved flytting av fil", "Error" => "Feil", "Name" => "Namn", "Size" => "Storleik", "Modified" => "Endra", +"_%n folder_::_%n folders_" => array("%n mappe","%n mapper"), +"_%n file_::_%n files_" => array("%n fil","%n filer"), +"_Uploading %n file_::_Uploading %n files_" => array("Lastar opp %n fil","Lastar opp %n filer"), +"Your storage is full, files can not be updated or synced anymore!" => "Lagringa di er full, kan ikkje lenger oppdatera eller synkronisera!", +"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.", +"{dirs} and {files}" => "{dirs} og {files}", "%s could not be renamed" => "Klarte ikkje å omdøypa på %s", -"Upload" => "Last opp", "File handling" => "Filhandtering", "Maximum upload size" => "Maksimal opplastingsstorleik", "max. possible: " => "maks. moglege:", @@ -57,6 +52,7 @@ $TRANSLATIONS = array( "Save" => "Lagre", "New" => "Ny", "Text file" => "Tekst fil", +"New folder" => "Ny mappe", "Folder" => "Mappe", "From link" => "Frå lenkje", "Deleted files" => "Sletta filer", @@ -67,7 +63,6 @@ $TRANSLATIONS = array( "Upload too large" => "For stor opplasting", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filene du prøver å lasta opp er større enn maksgrensa til denne tenaren.", "Files are being scanned, please wait." => "Skannar filer, ver venleg og vent.", -"Current scanning" => "Køyrande skanning", -"Upgrading filesystem cache..." => "Oppgraderer mellomlageret av filsystemet …" +"Current scanning" => "Køyrande skanning" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/oc.php b/apps/files/l10n/oc.php index eb1a9038b0..3683ae433a 100644 --- a/apps/files/l10n/oc.php +++ b/apps/files/l10n/oc.php @@ -12,15 +12,13 @@ $TRANSLATIONS = array( "Share" => "Parteja", "Rename" => "Torna nomenar", "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", -"Upload" => "Amontcarga", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "File handling" => "Manejament de fichièr", "Maximum upload size" => "Talha maximum d'amontcargament", "max. possible: " => "max. possible: ", diff --git a/apps/files/l10n/or_IN.php b/apps/files/l10n/or_IN.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/or_IN.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/pa.php b/apps/files/l10n/pa.php index 63fcbe12dd..3cf8724249 100644 --- a/apps/files/l10n/pa.php +++ b/apps/files/l10n/pa.php @@ -3,12 +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" => "ਡਾਊਨਲੋਡ", "Delete" => "ਹਟਾਓ" diff --git a/apps/files/l10n/pl.php b/apps/files/l10n/pl.php index 031bd50870..fa9c791144 100644 --- a/apps/files/l10n/pl.php +++ b/apps/files/l10n/pl.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Nie można było przenieść %s - Plik o takiej nazwie już istnieje", "Could not move %s" => "Nie można było przenieść %s", "File name cannot be empty." => "Nazwa pliku nie może być pusta.", -"File name must not contain \"/\". Please choose a different name." => "Nazwa pliku nie może zawierać \"/\". Proszę wybrać inną nazwę.", +"\"%s\" is an invalid file name." => "\"%s\" jest nieprawidłową nazwą pliku.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nieprawidłowa nazwa. Znaki '\\', '/', '<', '>', ':', '\"', '|', '?' oraz '*' są niedozwolone.", +"The target folder has been moved or deleted." => "Folder docelowy został przeniesiony lub usunięty", "The name %s is already used in the folder %s. Please choose a different name." => "Nazwa %s jest już używana w folderze %s. Proszę wybrać inną nazwę.", "Not a valid source" => "Niepoprawne źródło", "Server is not allowed to open URLs, please check the server configuration" => "Serwer nie mógł otworzyć adresów URL, należy sprawdzić konfigurację serwera", "Error while downloading %s to %s" => "Błąd podczas pobierania %s do %S", "Error when creating the file" => "Błąd przy tworzeniu pliku", "Folder name cannot be empty." => "Nazwa folderu nie może być pusta.", -"Folder name must not contain \"/\". Please choose a different name." => "Nazwa folderu nie może zawierać \"/\". Proszę wybrać inną nazwę.", "Error when creating the folder" => "Błąd przy tworzeniu folderu", "Unable to set upload directory." => "Nie można ustawić katalog wczytywania.", "Invalid Token" => "Nieprawidłowy Token", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Brak folderu tymczasowego", "Failed to write to disk" => "Błąd zapisu na dysk", "Not enough storage available" => "Za mało dostępnego miejsca", -"Upload failed. Could not get file info." => "Nieudane przesłanie. Nie można pobrać informacji o pliku.", "Upload failed. Could not find uploaded file" => "Nieudane przesłanie. Nie można znaleźć przesyłanego pliku", +"Upload failed. Could not get file info." => "Nieudane przesłanie. Nie można pobrać informacji o pliku.", "Invalid directory." => "Zła ścieżka.", "Files" => "Pliki", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Nie można przesłać {filename} być może jest katalogiem lub posiada 0 bajtów", -"Not enough space available" => "Za mało miejsca", +"Total file size {size1} exceeds upload limit {size2}" => "Całkowity rozmiar {size1} przekracza limit uploadu {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Brak wolnej przestrzeni, przesyłasz {size1} a pozostało tylko {size2}", "Upload cancelled." => "Wczytywanie anulowane.", "Could not get result from server." => "Nie można uzyskać wyniku z serwera.", "File upload is in progress. Leaving the page now will cancel the upload." => "Wysyłanie pliku jest w toku. Jeśli opuścisz tę stronę, wysyłanie zostanie przerwane.", "URL cannot be empty" => "URL nie może być pusty", -"In the home folder 'Shared' is a reserved filename" => "W katalogu domowym \"Shared\" jest zarezerwowana nazwa pliku", "{new_name} already exists" => "{new_name} już istnieje", "Could not create file" => "Nie można utworzyć pliku", "Could not create folder" => "Nie można utworzyć folderu", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Udostępnij", "Delete permanently" => "Trwale usuń", "Rename" => "Zmień nazwę", +"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.", "Pending" => "Oczekujące", +"Error moving file." => "Błąd podczas przenoszenia pliku.", +"Error moving file" => "Błąd prz przenoszeniu pliku", +"Error" => "Błąd", "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", +"Name" => "Nazwa", +"Size" => "Rozmiar", +"Modified" => "Modyfikacja", "_%n folder_::_%n folders_" => array("%n katalog","%n katalogi","%n katalogów"), "_%n file_::_%n files_" => array("%n plik","%n pliki","%n plików"), -"{dirs} and {files}" => "{dirs} and {files}", "_Uploading %n file_::_Uploading %n files_" => array("Wysyłanie %n pliku","Wysyłanie %n plików","Wysyłanie %n plików"), -"'.' is an invalid file name." => "„.” jest nieprawidłową nazwą pliku.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nieprawidłowa nazwa. Znaki '\\', '/', '<', '>', ':', '\"', '|', '?' oraz '*' są niedozwolone.", +"\"{name}\" is an invalid file name." => "\"{name}\" jest nieprawidłową nazwą pliku.", "Your storage is full, files can not be updated or synced anymore!" => "Magazyn jest pełny. Pliki nie mogą zostać zaktualizowane lub zsynchronizowane!", "Your storage is almost full ({usedSpacePercent}%)" => "Twój magazyn jest prawie pełny ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Aplikacja szyfrująca jest aktywna, ale twoje klucze nie zostały zainicjowane, prosze wyloguj się i zaloguj ponownie.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Niepoprawna nazwa folderu. Wykorzystanie \"Shared\" jest zarezerwowane.", +"{dirs} and {files}" => "{dirs} i {files}", "%s could not be renamed" => "%s nie można zmienić nazwy", -"Upload" => "Wyślij", +"Upload (max. %s)" => "Wysyłka (max. %s)", "File handling" => "Zarządzanie plikami", "Maximum upload size" => "Maksymalny rozmiar wysyłanego pliku", "max. possible: " => "maks. możliwy:", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Ładowany plik jest za duży", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Pliki, które próbujesz przesłać, przekraczają maksymalną dopuszczalną wielkość.", "Files are being scanned, please wait." => "Skanowanie plików, proszę czekać.", -"Current scanning" => "Aktualnie skanowane", -"Upgrading filesystem cache..." => "Uaktualnianie plików pamięci podręcznej..." +"Current scanning" => "Aktualnie skanowane" ); $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/pl_PL.php b/apps/files/l10n/pl_PL.php deleted file mode 100644 index b67f67b972..0000000000 --- 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 f84dcfcd48..5e0399bc4e 100644 --- a/apps/files/l10n/pt_BR.php +++ b/apps/files/l10n/pt_BR.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Impossível mover %s - Um arquivo com este nome já existe", "Could not move %s" => "Impossível mover %s", "File name cannot be empty." => "O nome do arquivo não pode estar vazio.", -"File name must not contain \"/\". Please choose a different name." => "O nome do arquivo não deve conter \"/\". Por favor, escolha um nome diferente.", +"\"%s\" is an invalid file name." => "\"%s\" é um nome de arquivo inválido.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome inválido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", +"The target folder has been moved or deleted." => "A pasta de destino foi movida ou excluída.", "The name %s is already used in the folder %s. Please choose a different name." => "O nome %s já é usado na pasta %s. Por favor, escolha um nome diferente.", "Not a valid source" => "Não é uma fonte válida", "Server is not allowed to open URLs, please check the server configuration" => "Não é permitido ao servidor abrir URLs, por favor verificar a configuração do servidor.", "Error while downloading %s to %s" => "Erro ao baixar %s para %s", "Error when creating the file" => "Erro ao criar o arquivo", "Folder name cannot be empty." => "O nome da pasta não pode estar vazio.", -"Folder name must not contain \"/\". Please choose a different name." => "O nome da pasta não pode conter \"/\". Por favor, escolha um nome diferente.", "Error when creating the folder" => "Erro ao criar a pasta", "Unable to set upload directory." => "Impossível configurar o diretório de upload", "Invalid Token" => "Token inválido", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Pasta temporária não encontrada", "Failed to write to disk" => "Falha ao escrever no disco", "Not enough storage available" => "Espaço de armazenamento insuficiente", -"Upload failed. Could not get file info." => "Falha no envio. Não foi possível obter informações do arquivo.", "Upload failed. Could not find uploaded file" => "Falha no envio. Não foi possível encontrar o arquivo enviado", +"Upload failed. Could not get file info." => "Falha no envio. Não foi possível obter informações do arquivo.", "Invalid directory." => "Diretório inválido.", "Files" => "Arquivos", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Incapaz de fazer o envio de {filename}, pois é um diretório ou tem 0 bytes", -"Not enough space available" => "Espaço de armazenamento insuficiente", +"Total file size {size1} exceeds upload limit {size2}" => "Tamanho total do arquivo {size1} excede limite de envio {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Não há espaço suficiente, você está enviando {size1} mas resta apenas {size2}", "Upload cancelled." => "Envio cancelado.", "Could not get result from server." => "Não foi possível obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "Upload em andamento. Sair da página agora resultará no cancelamento do envio.", "URL cannot be empty" => "URL não pode estar vazia", -"In the home folder 'Shared' is a reserved filename" => "Na pasta home 'Shared- Compartilhada' é um nome reservado", "{new_name} already exists" => "{new_name} já existe", "Could not create file" => "Não foi possível criar o arquivo", "Could not create folder" => "Não foi possível criar a pasta", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Compartilhar", "Delete permanently" => "Excluir permanentemente", "Rename" => "Renomear", +"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.", "Pending" => "Pendente", +"Error moving file." => "Erro movendo o arquivo.", +"Error moving file" => "Erro movendo o arquivo", +"Error" => "Erro", "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.", +"Name" => "Nome", +"Size" => "Tamanho", +"Modified" => "Modificado", "_%n folder_::_%n folders_" => array("%n pasta","%n pastas"), "_%n file_::_%n files_" => array("%n arquivo","%n arquivos"), -"{dirs} and {files}" => "{dirs} e {files}", "_Uploading %n file_::_Uploading %n files_" => array("Enviando %n arquivo","Enviando %n arquivos"), -"'.' is an invalid file name." => "'.' é um nome de arquivo inválido.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome inválido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", +"\"{name}\" is an invalid file name." => "\"{name}\" é um nome de arquivo inválido.", "Your storage is full, files can not be updated or synced anymore!" => "Seu armazenamento está cheio, arquivos não podem mais ser atualizados ou sincronizados!", "Your storage is almost full ({usedSpacePercent}%)" => "Seu armazenamento está quase cheio ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "App de encriptação está ativado, mas as chaves não estão inicializadas, por favor log-out e faça login novamente", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Nome da pasta inválido. Uso de 'Shared' é reservado.", +"{dirs} and {files}" => "{dirs} e {files}", "%s could not be renamed" => "%s não pode ser renomeado", -"Upload" => "Upload", +"Upload (max. %s)" => "Envio (max. %s)", "File handling" => "Tratamento de Arquivo", "Maximum upload size" => "Tamanho máximo para carregar", "max. possible: " => "max. possível:", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Upload muito grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os arquivos que você está tentando carregar excedeu o tamanho máximo para arquivos no servidor.", "Files are being scanned, please wait." => "Arquivos sendo escaneados, por favor aguarde.", -"Current scanning" => "Scanning atual", -"Upgrading filesystem cache..." => "Atualizando cache do sistema de arquivos..." +"Current scanning" => "Scanning atual" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files/l10n/pt_PT.php b/apps/files/l10n/pt_PT.php index 4b9fade2e2..c6d2767fb8 100644 --- a/apps/files/l10n/pt_PT.php +++ b/apps/files/l10n/pt_PT.php @@ -1,8 +1,16 @@ "Não foi possível mover o ficheiro %s - Já existe um ficheiro com esse nome", +"Could not move %s - File with this name already exists" => "Não pôde mover o ficheiro %s - Já existe um ficheiro com esse nome", "Could not move %s" => "Não foi possível move o ficheiro %s", "File name cannot be empty." => "O nome do ficheiro não pode estar vazio.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome Inválido, os caracteres '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", +"The name %s is already used in the folder %s. Please choose a different name." => "O nome %s já está em uso na pasta %s. Por favor escolha um nome diferente.", +"Not a valid source" => "Não é uma fonte válida", +"Server is not allowed to open URLs, please check the server configuration" => "O servidor não consegue abrir URLs, por favor verifique a configuração do servidor", +"Error while downloading %s to %s" => "Erro ao transferir %s para %s", +"Error when creating the file" => "Erro ao criar o ficheiro", +"Folder name cannot be empty." => "O nome da pasta não pode estar vazio.", +"Error when creating the folder" => "Erro ao criar a pasta", "Unable to set upload directory." => "Não foi possível criar o diretório de upload", "Invalid Token" => "Token inválido", "No file was uploaded. Unknown error" => "Nenhum ficheiro foi carregado. Erro desconhecido", @@ -14,37 +22,41 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Está a faltar a pasta temporária", "Failed to write to disk" => "Falhou a escrita no disco", "Not enough storage available" => "Não há espaço suficiente em disco", +"Upload failed. Could not find uploaded file" => "Falhou o envio. Não conseguiu encontrar o ficheiro enviado", "Upload failed. Could not get file info." => "O carregamento falhou. Não foi possível obter a informação do ficheiro.", "Invalid directory." => "Directório Inválido", "Files" => "Ficheiros", -"Not enough space available" => "Espaço em disco insuficiente!", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "Incapaz de enviar {filename}, dado que é uma pasta, ou tem 0 bytes", "Upload cancelled." => "Envio cancelado.", "Could not get result from server." => "Não foi possível obter o resultado do servidor.", "File upload is in progress. Leaving the page now will cancel the upload." => "Envio de ficheiro em progresso. Irá cancelar o envio se sair da página agora.", +"URL cannot be empty" => "URL não pode estar vazio", "{new_name} already exists" => "O nome {new_name} já existe", +"Could not create file" => "Não pôde criar ficheiro", +"Could not create folder" => "Não pôde criar pasta", +"Error fetching URL" => "Erro ao obter URL", "Share" => "Partilhar", "Delete permanently" => "Eliminar permanentemente", "Rename" => "Renomear", -"Pending" => "Pendente", -"replaced {new_name} with {old_name}" => "substituido {new_name} por {old_name}", -"undo" => "desfazer", -"_%n folder_::_%n folders_" => array("%n pasta","%n pastas"), -"_%n file_::_%n files_" => array("%n ficheiro","%n ficheiros"), -"{dirs} and {files}" => "{dirs} e {files}", -"_Uploading %n file_::_Uploading %n files_" => array("A carregar %n ficheiro","A carregar %n ficheiros"), -"'.' is an invalid file name." => "'.' não é um nome de ficheiro válido!", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome Inválido, os caracteres '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", -"Your storage is full, files can not be updated or synced anymore!" => "O seu armazenamento está cheio, os ficheiros não podem ser sincronizados.", -"Your storage is almost full ({usedSpacePercent}%)" => "O seu espaço de armazenamento está quase cheiro ({usedSpacePercent}%)", -"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.", +"Pending" => "Pendente", "Error moving file" => "Erro ao mover o ficheiro", "Error" => "Erro", +"Could not rename file" => "Não pôde renomear o ficheiro", +"Error deleting file." => "Erro ao apagar o ficheiro.", "Name" => "Nome", "Size" => "Tamanho", "Modified" => "Modificado", +"_%n folder_::_%n folders_" => array("%n pasta","%n pastas"), +"_%n file_::_%n files_" => array("%n ficheiro","%n ficheiros"), +"_Uploading %n file_::_Uploading %n files_" => array("A carregar %n ficheiro","A carregar %n ficheiros"), +"Your storage is full, files can not be updated or synced anymore!" => "O seu armazenamento está cheio, os ficheiros não podem ser sincronizados.", +"Your storage is almost full ({usedSpacePercent}%)" => "O seu espaço de armazenamento está quase cheiro ({usedSpacePercent}%)", +"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "A Aplicação de Encriptação está ativada, mas as suas chaves não inicializaram. Por favor termine e inicie a sessão novamente", +"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.", +"{dirs} and {files}" => "{dirs} e {files}", "%s could not be renamed" => "%s não pode ser renomeada", -"Upload" => "Carregar", "File handling" => "Manuseamento de ficheiros", "Maximum upload size" => "Tamanho máximo de envio", "max. possible: " => "max. possivel: ", @@ -54,19 +66,20 @@ $TRANSLATIONS = array( "Maximum input size for ZIP files" => "Tamanho máximo para ficheiros ZIP", "Save" => "Guardar", "New" => "Novo", +"New text file" => "Novo ficheiro de texto", "Text file" => "Ficheiro de texto", "New folder" => "Nova Pasta", "Folder" => "Pasta", "From link" => "Da ligação", "Deleted files" => "Ficheiros eliminados", "Cancel upload" => "Cancelar envio", +"You don’t have permission to upload or create files here" => "Você não tem permissão para enviar ou criar ficheiros aqui", "Nothing in here. Upload something!" => "Vazio. Envie alguma coisa!", "Download" => "Transferir", "Delete" => "Eliminar", "Upload too large" => "Upload muito grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os ficheiro que está a tentar enviar excedem o tamanho máximo de envio neste servidor.", "Files are being scanned, please wait." => "Os ficheiros estão a ser analisados, por favor aguarde.", -"Current scanning" => "Análise actual", -"Upgrading filesystem cache..." => "Atualizar cache do sistema de ficheiros..." +"Current scanning" => "Análise actual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ro.php b/apps/files/l10n/ro.php index 933625d8d1..c36ba11fc0 100644 --- a/apps/files/l10n/ro.php +++ b/apps/files/l10n/ro.php @@ -1,73 +1,92 @@ "%s nu se poate muta - Fișierul cu acest nume există deja ", -"Could not move %s" => "Nu s-a putut muta %s", +"Could not move %s" => "Nu se poate muta %s", "File name cannot be empty." => "Numele fișierului nu poate rămâne gol.", +"\"%s\" is an invalid file name." => "\"%s\" este un nume de fișier nevalid", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nume nevalide, '\\', '/', '<', '>', ':', '\"', '|', '?' și '*' nu sunt permise.", +"The target folder has been moved or deleted." => "Dosarul țintă a fost mutat sau șters.", +"The name %s is already used in the folder %s. Please choose a different name." => "Numele %s este deja este folosit în dosarul %s. Te rog alege alt nume.", +"Not a valid source" => "Sursă nevalidă", +"Server is not allowed to open URLs, please check the server configuration" => "Serverului nu ii este permis sa deschida URL-ul , verificati setarile serverului", +"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", -"No file was uploaded. Unknown error" => "Nici un fișier nu a fost încărcat. Eroare necunoscută", +"No file was uploaded. Unknown error" => "Niciun fișier nu a fost încărcat. Eroare necunoscută", "There is no error, the file uploaded with success" => "Nu a apărut nici o eroare, fișierul a fost încărcat cu succes", -"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Fisierul incarcat depaseste marimea maxima permisa in php.ini: ", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Fișierul are o dimensiune mai mare decât variabile MAX_FILE_SIZE specificată în formularul HTML", +"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Fișierul încărcat depășește directiva upload_max_filesize din php.ini:", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Fișierul încărcat depășește directiva MAX_FILE_SIZE specificată în formularul HTML", "The uploaded file was only partially uploaded" => "Fișierul a fost încărcat doar parțial", -"No file was uploaded" => "Nu a fost încărcat nici un fișier", +"No file was uploaded" => "Nu a fost încărcat niciun fișier", "Missing a temporary folder" => "Lipsește un dosar temporar", -"Failed to write to disk" => "Eroare la scrierea discului", -"Not enough storage available" => "Nu este suficient spațiu disponibil", -"Upload failed. Could not get file info." => "Încărcare eșuată. Nu se pot obține informații despre fișier.", +"Failed to write to disk" => "Eroare la scrierea pe disc", +"Not enough storage available" => "Nu este disponibil suficient spațiu", "Upload failed. Could not find uploaded file" => "Încărcare eșuată. Nu se poate găsi fișierul încărcat", -"Invalid directory." => "registru invalid.", +"Upload failed. Could not get file info." => "Încărcare eșuată. Nu se pot obține informații despre fișier.", +"Invalid directory." => "Dosar nevalid.", "Files" => "Fișiere", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți", -"Not enough space available" => "Nu este suficient spațiu disponibil", +"Total file size {size1} exceeds upload limit {size2}" => "Mărimea fișierului este {size1} ce depășește limita de incarcare de {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas", "Upload cancelled." => "Încărcare anulată.", "Could not get result from server." => "Nu se poate obține rezultatul de la server.", "File upload is in progress. Leaving the page now will cancel the upload." => "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.", -"{new_name} already exists" => "{new_name} deja exista", -"Share" => "a imparti", -"Delete permanently" => "Stergere permanenta", -"Rename" => "Redenumire", -"Pending" => "in timpul", -"replaced {new_name} with {old_name}" => "{new_name} inlocuit cu {old_name}", -"undo" => "Anulează ultima acțiune", -"_%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}", -"_Uploading %n file_::_Uploading %n files_" => array("Se încarcă %n fișier.","Se încarcă %n fișiere.","Se încarcă %n fișiere."), -"'.' is an invalid file name." => "'.' este un nume invalid de fișier.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nume invalide, '\\', '/', '<', '>', ':', '\"', '|', '?' si '*' nu sunt permise.", -"Your storage is full, files can not be updated or synced anymore!" => "Spatiul de stocare este plin, fisierele nu mai pot fi actualizate sau sincronizate", -"Your storage is almost full ({usedSpacePercent}%)" => "Spatiul de stocare este aproape plin {spatiu folosit}%", -"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." => "in curs de descarcare. Aceasta poate să dureze ceva timp dacă fișierele sunt mari.", +"URL cannot be empty" => "URL nu poate fi gol", +"{new_name} already exists" => "{new_name} există deja", +"Could not create file" => "Nu s-a putut crea fisierul", +"Could not create folder" => "Nu s-a putut crea folderul", +"Error fetching URL" => "Eroare încarcare URL", +"Share" => "Partajează", +"Delete permanently" => "Șterge permanent", +"Rename" => "Redenumește", +"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.", +"Pending" => "În așteptare", +"Error moving file." => "Eroare la mutarea fișierului.", "Error moving file" => "Eroare la mutarea fișierului", "Error" => "Eroare", +"Could not rename file" => "Nu s-a putut redenumi fisierul", +"Error deleting file." => "Eroare la ștergerea fisierului.", "Name" => "Nume", -"Size" => "Dimensiune", +"Size" => "Mărime", "Modified" => "Modificat", +"_%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"), +"_Uploading %n file_::_Uploading %n files_" => array("Se încarcă %n fișier.","Se încarcă %n fișiere.","Se încarcă %n fișiere."), +"\"{name}\" is an invalid file name." => "\"{name}\" este un nume de fișier nevalid.", +"Your storage is full, files can not be updated or synced anymore!" => "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!", +"Your storage is almost full ({usedSpacePercent}%)" => "Spațiul de stocare este aproape plin ({usedSpacePercent}%)", +"Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Aplicatia de criptare este activata dar tastatura nu este initializata , va rugam deconectati-va si reconectati-va", +"Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files." => "Cheie privată nevalidă pentru aplicația Încriptare. Te rog, actualizează-ți parola cheii private folosind setările personale pentru a reaccesa fișierele tale încriptate.", +"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", +"{dirs} and {files}" => "{dirs} și {files}", "%s could not be renamed" => "%s nu a putut fi redenumit", -"Upload" => "Încărcare", +"Upload (max. %s)" => "Încarcă (max. %s)", "File handling" => "Manipulare fișiere", "Maximum upload size" => "Dimensiune maximă admisă la încărcare", "max. possible: " => "max. posibil:", -"Needed for multi-file and folder downloads." => "necesar la descarcarea mai multor liste si fisiere", -"Enable ZIP-download" => "permite descarcarea codurilor ZIP", -"0 is unlimited" => "0 e nelimitat", -"Maximum input size for ZIP files" => "Dimensiunea maximă de intrare pentru fișiere compresate", +"Needed for multi-file and folder downloads." => "Necesar pentru descărcarea mai multor fișiere și a dosarelor.", +"Enable ZIP-download" => "Permite descărcarea ZIP", +"0 is unlimited" => "0 este nelimitat", +"Maximum input size for ZIP files" => "Dimensiunea maximă de intrare pentru fișierele ZIP", "Save" => "Salvează", "New" => "Nou", -"Text file" => "lista", +"New text file" => "Un nou fișier text", +"Text file" => "Fișier text", +"New folder" => "Un nou dosar", "Folder" => "Dosar", -"From link" => "de la adresa", -"Deleted files" => "Sterge fisierele", +"From link" => "De la adresa", +"Deleted files" => "Fișiere șterse", "Cancel upload" => "Anulează încărcarea", +"You don’t have permission to upload or create files here" => "Nu aveti permisiunea de a incarca sau crea fisiere aici", "Nothing in here. Upload something!" => "Nimic aici. Încarcă ceva!", "Download" => "Descarcă", "Delete" => "Șterge", "Upload too large" => "Fișierul încărcat este prea mare", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Fișierul care l-ai încărcat a depășită limita maximă admisă la încărcare pe acest server.", -"Files are being scanned, please wait." => "Fișierele sunt scanate, asteptati va rog", -"Current scanning" => "În curs de scanare", -"Upgrading filesystem cache..." => "Modernizare fisiere de sistem cache.." +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Fișierele pe care încerci să le încarci depășesc limita de încărcare maximă admisă pe acest server.", +"Files are being scanned, please wait." => "Fișierele sunt scanate, te rog așteaptă.", +"Current scanning" => "În curs de scanare" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"; diff --git a/apps/files/l10n/ru.php b/apps/files/l10n/ru.php index 968da63aac..181e063e60 100644 --- a/apps/files/l10n/ru.php +++ b/apps/files/l10n/ru.php @@ -3,93 +3,89 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Невозможно переместить %s - файл с таким именем уже существует", "Could not move %s" => "Невозможно переместить %s", "File name cannot be empty." => "Имя файла не может быть пустым.", -"File name must not contain \"/\". Please choose a different name." => "Имя файла не должно содержать символ \"/\". Пожалуйста, выберите другое имя.", -"The name %s is already used in the folder %s. Please choose a different name." => "Имя %s уже используется в папке %s. Пожалуйста выберите другое имя.", +"\"%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-адреса, пожалуйста, проверьте настройки сервера", -"Error while downloading %s to %s" => "Ошибка при загрузке %s в %s", +"Error while downloading %s to %s" => "Ошибка при скачивании %s в %s", "Error when creating the file" => "Ошибка при создании файла", "Folder name cannot be empty." => "Имя папки не может быть пустым.", -"Folder name must not contain \"/\". Please choose a different name." => "Имя папки не должно содержать символ \"/\". Пожалуйста, выберите другое имя.", -"Error when creating the folder" => "Ошибка при создании папки", +"Error when creating the folder" => "Ошибка создания каталога", "Unable to set upload directory." => "Не удалось установить каталог загрузки.", "Invalid Token" => "Недопустимый маркер", "No file was uploaded. Unknown error" => "Файл не был загружен. Неизвестная ошибка", "There is no error, the file uploaded with success" => "Файл загружен успешно.", -"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Файл превышает размер установленный upload_max_filesize в php.ini:", -"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Загружаемый файл превосходит значение переменной MAX_FILE_SIZE, указанной в форме HTML", -"The uploaded file was only partially uploaded" => "Файл загружен частично", -"No file was uploaded" => "Файл не был загружен", -"Missing a temporary folder" => "Отсутствует временная папка", +"The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Файл превышает размер, установленный параметром upload_max_filesize в php.ini:", +"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "Загруженный файл превышает размер, установленный параметром MAX_FILE_SIZE в HTML-форме", +"The uploaded file was only partially uploaded" => "Файл загружен лишь частично", +"No file was uploaded" => "Ни одного файла загружено не было", +"Missing a temporary folder" => "Отсутствует временный каталог", "Failed to write to disk" => "Ошибка записи на диск", "Not enough storage available" => "Недостаточно доступного места в хранилище", +"Upload failed. Could not find uploaded file" => "Загрузка не удалась. Невозможно найти загружаемый файл", "Upload failed. Could not get file info." => "Загрузка не удалась. Невозможно получить информацию о файле", -"Upload failed. Could not find uploaded file" => "Загрузка не удалась. Невозможно найти загруженный файл", -"Invalid directory." => "Неправильный каталог.", +"Invalid directory." => "Неверный каталог.", "Files" => "Файлы", -"Unable to upload {filename} as it is a directory or has 0 bytes" => "Невозможно загрузить файл {filename} так как он является директорией либо имеет размер 0 байт", -"Not enough space available" => "Недостаточно свободного места", +"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." => "Файл в процессе загрузки. Покинув страницу вы прервёте загрузку.", +"Could not get result from server." => "Не удалось получить ответ от сервера.", +"File upload is in progress. Leaving the page now will cancel the upload." => "Идёт загрузка файла. Покинув страницу, вы прервёте загрузку.", "URL cannot be empty" => "Ссылка не может быть пустой.", -"In the home folder 'Shared' is a reserved filename" => "В домашней папке 'Shared' зарезервированное имя файла", "{new_name} already exists" => "{new_name} уже существует", "Could not create file" => "Не удалось создать файл", -"Could not create folder" => "Не удалось создать папку", +"Could not create folder" => "Не удалось создать каталог", "Error fetching URL" => "Ошибка получения URL", "Share" => "Открыть доступ", -"Delete permanently" => "Удалено навсегда", +"Delete permanently" => "Удалить окончательно", "Rename" => "Переименовать", +"Your download is being prepared. This might take some time if the files are big." => "Идёт подготовка к скачиванию. Это может занять некоторое время, если файлы большого размера.", "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 файлов"), -"'.' is an invalid file name." => "'.' - неправильное имя файла.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неправильное имя, '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' недопустимы.", -"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" => "Ошибка", +"Could not rename file" => "Не удалось переименовать файл", +"Error deleting file." => "Ошибка при удалении файла.", "Name" => "Имя", "Size" => "Размер", -"Modified" => "Изменён", -"Invalid folder name. Usage of 'Shared' is reserved." => "Неправильное имя каталога. Имя 'Shared' зарезервировано.", +"Modified" => "Дата изменения", +"_%n folder_::_%n folders_" => array("%n каталог","%n каталога","%n каталогов"), +"_%n file_::_%n files_" => array("%n файл","%n файла","%n файлов"), +"_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." => "Шифрование было отключено, но ваши файлы остались зашифрованными. Зайдите на страницу личных настроек для того, чтобы расшифровать их.", +"{dirs} and {files}" => "{dirs} и {files}", "%s could not be renamed" => "%s не может быть переименован", -"Upload" => "Загрузка", +"Upload (max. %s)" => "Загружено (max. %s)", "File handling" => "Управление файлами", "Maximum upload size" => "Максимальный размер загружаемого файла", "max. possible: " => "макс. возможно: ", "Needed for multi-file and folder downloads." => "Требуется для скачивания нескольких файлов и папок", -"Enable ZIP-download" => "Включить ZIP-скачивание", +"Enable ZIP-download" => "Включить скачивание в виде архивов ZIP", "0 is unlimited" => "0 - без ограничений", "Maximum input size for ZIP files" => "Максимальный исходный размер для ZIP файлов", "Save" => "Сохранить", "New" => "Новый", "New text file" => "Новый текстовый файл", "Text file" => "Текстовый файл", -"New folder" => "Новая папка", -"Folder" => "Папка", -"From link" => "Из ссылки", +"New folder" => "Новый каталог", +"Folder" => "Каталог", +"From link" => "Объект по ссылке", "Deleted files" => "Удалённые файлы", -"Cancel upload" => "Отмена загрузки", -"You don’t have permission to upload or create files here" => "У вас недостаточно прав для загрузки или создания файлов отсюда.", +"Cancel upload" => "Отменить загрузку", +"You don’t have permission to upload or create files here" => "У вас нет прав для загрузки или создания файлов здесь.", "Nothing in here. Upload something!" => "Здесь ничего нет. Загрузите что-нибудь!", "Download" => "Скачать", "Delete" => "Удалить", "Upload too large" => "Файл слишком велик", -"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файлы, которые вы пытаетесь загрузить, превышают лимит для файлов на этом сервере.", +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файлы, которые вы пытаетесь загрузить, превышают лимит максимального размера на этом сервере.", "Files are being scanned, please wait." => "Подождите, файлы сканируются.", -"Current scanning" => "Текущее сканирование", -"Upgrading filesystem cache..." => "Обновление кэша файловой системы..." +"Current scanning" => "Текущее сканирование" ); $PLURAL_FORMS = "nplurals=3; 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/si_LK.php b/apps/files/l10n/si_LK.php index 44decfef1b..e8d2a8a53c 100644 --- a/apps/files/l10n/si_LK.php +++ b/apps/files/l10n/si_LK.php @@ -12,15 +12,13 @@ $TRANSLATIONS = array( "File upload is in progress. Leaving the page now will cancel the upload." => "උඩුගතකිරීමක් සිදුවේ. පිටුව හැර යාමෙන් එය නැවතෙනු ඇත", "Share" => "බෙදා හදා ගන්න", "Rename" => "නැවත නම් කරන්න", -"undo" => "නිෂ්ප්‍රභ කරන්න", -"_%n folder_::_%n folders_" => array("",""), -"_%n file_::_%n files_" => array("",""), -"_Uploading %n file_::_Uploading %n files_" => array("",""), "Error" => "දෝෂයක්", "Name" => "නම", "Size" => "ප්‍රමාණය", "Modified" => "වෙනස් කළ", -"Upload" => "උඩුගත කරන්න", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "File handling" => "ගොනු පරිහරණය", "Maximum upload size" => "උඩුගත කිරීමක උපරිම ප්‍රමාණය", "max. possible: " => "හැකි උපරිමය:", diff --git a/apps/files/l10n/sk_SK.php b/apps/files/l10n/sk_SK.php index 2d0eb25f62..66f1c616e4 100644 --- a/apps/files/l10n/sk_SK.php +++ b/apps/files/l10n/sk_SK.php @@ -3,13 +3,15 @@ $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", -"File name must not contain \"/\". Please choose a different name." => "Názov súboru nesmie obsahovať \"/\". Prosím zvoľte iný názov.", +"\"%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.", "Error while downloading %s to %s" => "Chyba pri sťahovaní súboru %s do %s", "Error when creating the file" => "Chyba pri vytváraní súboru", "Folder name cannot be empty." => "Názov priečinka nemôže byť prázdny.", -"Folder name must not contain \"/\". Please choose a different name." => "Názov priečinka nesmie obsahovať \"/\". Prosím zvoľte iný názov.", "Error when creating the folder" => "Chyba pri vytváraní priečinka", "Unable to set upload directory." => "Nemožno nastaviť priečinok pre nahrané súbory.", "Invalid Token" => "Neplatný token", @@ -22,48 +24,45 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Chýba dočasný priečinok", "Failed to write to disk" => "Zápis na disk sa nepodaril", "Not enough storage available" => "Nedostatok dostupného úložného priestoru", -"Upload failed. Could not get file info." => "Nahrávanie zlyhalo. Nepodarilo sa získať informácie o súbore.", "Upload failed. Could not find uploaded file" => "Nahrávanie zlyhalo. Nepodarilo sa nájsť nahrávaný súbor", +"Upload failed. Could not get file info." => "Nahrávanie zlyhalo. Nepodarilo sa získať informácie o súbore.", "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", -"Not enough space available" => "Nie je k dispozícii dostatok miesta", +"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.", "URL cannot be empty" => "URL nemôže byť prázdna", -"In the home folder 'Shared' is a reserved filename" => "V domovskom priečinku je názov \"Shared\" vyhradený názov súboru", "{new_name} already exists" => "{new_name} už existuje", "Could not create file" => "Nemožno vytvoriť súbor", "Could not create folder" => "Nemožno vytvoriť priečinok", +"Error fetching URL" => "Chyba pri načítavaní URL", "Share" => "Zdieľať", "Delete permanently" => "Zmazať trvalo", "Rename" => "Premenovať", +"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ť.", "Pending" => "Prebieha", +"Error moving file" => "Chyba pri presúvaní súboru", +"Error" => "Chyba", "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.", +"Name" => "Názov", +"Size" => "Veľkosť", +"Modified" => "Upravené", "_%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"), -"'.' is an invalid file name." => "'.' je neplatné meno súboru.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nesprávne meno, '\\', '/', '<', '>', ':', '\"', '|', '?' a '*' nie sú povolené hodnoty.", +"\"{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é", -"Invalid folder name. Usage of 'Shared' is reserved." => "Názov priečinka je chybný. Použitie názvu 'Shared' nie je povolené.", +"{dirs} and {files}" => "{dirs} a {files}", "%s could not be renamed" => "%s nemohol byť premenovaný", -"Upload" => "Odoslať", +"Upload (max. %s)" => "Nahrať (max. %s)", "File handling" => "Nastavenie správania sa k súborom", "Maximum upload size" => "Maximálna veľkosť odosielaného súboru", "max. possible: " => "najväčšie možné:", @@ -87,7 +86,6 @@ $TRANSLATIONS = array( "Upload too large" => "Nahrávanie je príliš veľké", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Súbory, ktoré sa snažíte nahrať, presahujú maximálnu veľkosť pre nahratie súborov na tento server.", "Files are being scanned, please wait." => "Čakajte, súbory sú prehľadávané.", -"Current scanning" => "Práve prezerané", -"Upgrading filesystem cache..." => "Aktualizujem medzipamäť súborového systému..." +"Current scanning" => "Práve prezerané" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/apps/files/l10n/sl.php b/apps/files/l10n/sl.php index 037e5f6b6b..90b18f632c 100644 --- a/apps/files/l10n/sl.php +++ b/apps/files/l10n/sl.php @@ -3,14 +3,15 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Datoteke %s ni mogoče premakniti - datoteka s tem imenom že obstaja.", "Could not move %s" => "Datoteke %s ni mogoče premakniti", "File name cannot be empty." => "Ime datoteke ne sme biti prazno polje.", -"File name must not contain \"/\". Please choose a different name." => "Ime datoteke ne sme vsebovati znaka \"/\". Določiti je treba drugo ime.", +"\"%s\" is an invalid file name." => "\"%s\" je neveljavno ime datoteke.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neveljavno ime; znaki '\\', '/', '<', '>', ':', '\"', '|', '?' in '*' niso dovoljeni.", +"The target folder has been moved or deleted." => "Ciljna mapa je premaknjena ali izbrisana.", "The name %s is already used in the folder %s. Please choose a different name." => "Ime %s je že v mapi %s že v uporabi. Izbrati je treba drugo ime.", "Not a valid source" => "Vir ni veljaven", "Server is not allowed to open URLs, please check the server configuration" => "Odpiranje naslovov URL preko strežnika ni dovoljeno. Preverite nastavitve strežnika.", "Error while downloading %s to %s" => "Napaka med prejemanjem %s v mapo %s", "Error when creating the file" => "Napaka med ustvarjanjem datoteke", "Folder name cannot be empty." => "Ime mape ne more biti prazna vrednost.", -"Folder name must not contain \"/\". Please choose a different name." => "Ime mape ne sme vsebovati znaka \"/\". Določiti je treba drugo ime.", "Error when creating the folder" => "Napaka med ustvarjanjem mape", "Unable to set upload directory." => "Mapo, v katero boste prenašali dokumente, ni mogoče določiti", "Invalid Token" => "Neveljaven žeton", @@ -23,17 +24,17 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Manjka začasna mapa", "Failed to write to disk" => "Pisanje na disk je spodletelo", "Not enough storage available" => "Na voljo ni dovolj prostora", -"Upload failed. Could not get file info." => "Pošiljanje je spodletelo. Ni mogoče pridobiti podrobnosti datoteke.", "Upload failed. Could not find uploaded file" => "Pošiljanje je spodletelo. Ni mogoče najti poslane datoteke.", +"Upload failed. Could not get file info." => "Pošiljanje je spodletelo. Ni mogoče pridobiti podrobnosti datoteke.", "Invalid directory." => "Neveljavna mapa.", "Files" => "Datoteke", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Ni mogoče poslati datoteke {filename}, saj je to ali mapa ali pa je velikost datoteke 0 bajtov.", -"Not enough space available" => "Na voljo ni dovolj prostora.", +"Total file size {size1} exceeds upload limit {size2}" => "Skupna velikost {size1} presega omejitev velikosti {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Na voljo ni dovolj prostora. Velikost poslane datoteke je {size1}, na voljo pa je je {size2}.", "Upload cancelled." => "Pošiljanje je preklicano.", "Could not get result from server." => "Ni mogoče pridobiti podatkov s strežnika.", "File upload is in progress. Leaving the page now will cancel the upload." => "V teku je pošiljanje datoteke. Če zapustite to stran zdaj, bo pošiljanje preklicano.", "URL cannot be empty" => "Polje naslova URL ne sme biti prazno", -"In the home folder 'Shared' is a reserved filename" => "V domači mapi ni dovoljeno ustvariti mape z imenom 'Souporabe', saj je ime zadržano za javno mapo.", "{new_name} already exists" => "{new_name} že obstaja", "Could not create file" => "Ni mogoče ustvariti datoteke", "Could not create folder" => "Ni mogoče ustvariti mape", @@ -41,31 +42,28 @@ $TRANSLATIONS = array( "Share" => "Souporaba", "Delete permanently" => "Izbriši dokončno", "Rename" => "Preimenuj", +"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.", "Pending" => "V čakanju ...", +"Error moving file." => "Napaka premikanja datoteke.", +"Error moving file" => "Napaka premikanja datoteke", +"Error" => "Napaka", "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.", +"Name" => "Ime", +"Size" => "Velikost", +"Modified" => "Spremenjeno", "_%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"), -"{dirs} and {files}" => "{dirs} in {files}", "_Uploading %n file_::_Uploading %n files_" => array("Posodabljanje %n datoteke","Posodabljanje %n datotek","Posodabljanje %n datotek","Posodabljanje %n datotek"), -"'.' is an invalid file name." => "'.' je neveljavno ime datoteke.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neveljavno ime; znaki '\\', '/', '<', '>', ':', '\"', '|', '?' in '*' niso dovoljeni.", +"\"{name}\" is an invalid file name." => "\"{name}\" je neveljavno ime datoteke.", "Your storage is full, files can not be updated or synced anymore!" => "Shramba je povsem napolnjena. Datotek ni več mogoče posodabljati in usklajevati!", "Your storage is almost full ({usedSpacePercent}%)" => "Prostor za shranjevanje je skoraj do konca zaseden ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Program za šifriranje je omogočen, vendar ni začet. Odjavite se in nato ponovno prijavite.", "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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Neveljavno ime mape. Ime 'Souporaba' je zadržana za javno mapo.", +"{dirs} and {files}" => "{dirs} in {files}", "%s could not be renamed" => "%s ni mogoče preimenovati", -"Upload" => "Pošlji", +"Upload (max. %s)" => "Pošiljanje (omejitev %s)", "File handling" => "Upravljanje z datotekami", "Maximum upload size" => "Največja velikost za pošiljanja", "max. possible: " => "največ mogoče:", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Prekoračenje omejitve velikosti", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Datoteke, ki jih želite poslati, presegajo največjo dovoljeno velikost na strežniku.", "Files are being scanned, please wait." => "Poteka preučevanje datotek, počakajte ...", -"Current scanning" => "Trenutno poteka preučevanje", -"Upgrading filesystem cache..." => "Nadgrajevanje predpomnilnika datotečnega sistema ..." +"Current scanning" => "Trenutno poteka preučevanje" ); $PLURAL_FORMS = "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"; diff --git a/apps/files/l10n/sq.php b/apps/files/l10n/sq.php index a06b6821af..d246fdd6d6 100644 --- a/apps/files/l10n/sq.php +++ b/apps/files/l10n/sq.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "E pa mundur zhvendosja e %s - ekziston nje skedar me te njetin emer", "Could not move %s" => "Nuk mund të zhvendoset %s", "File name cannot be empty." => "Emri i skedarit nuk mund të jetë bosh.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Emër jo i vlefshëm, '\\', '/', '<', '>', ':', '\"', '|', '?' dhe '*' nuk lejohen.", "Unable to set upload directory." => "E pa mundur të vendoset dosja e ngarkimit", "Invalid Token" => "Shenjë e gabuar", "No file was uploaded. Unknown error" => "Asnjë skedar nuk u dërgua. Gabim i pa njohur", @@ -16,32 +17,29 @@ $TRANSLATIONS = array( "Not enough storage available" => "Hapsira e arkivimit e pamjaftueshme", "Invalid directory." => "Dosje e pavlefshme", "Files" => "Skedarë", -"Not enough space available" => "Nuk ka hapsirë të nevojshme", "Upload cancelled." => "Ngarkimi u anullua", "File upload is in progress. Leaving the page now will cancel the upload." => "Skedari duke u ngarkuar. Largimi nga faqja do të anullojë ngarkimin", +"URL cannot be empty" => "URL-i nuk mund të jetë bosh", "{new_name} already exists" => "{new_name} është ekzistues ", +"Could not create folder" => "I pamundur krijimi i kartelës", "Share" => "Ndaj", "Delete permanently" => "Fshi përfundimisht", "Rename" => "Riemëro", -"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}", -"_Uploading %n file_::_Uploading %n files_" => array("Po ngarkoj %n skedar","Po ngarkoj %n skedarë"), -"'.' is an invalid file name." => "'.' nuk është skedar i vlefshem.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Emër jo i vlefshëm, '\\', '/', '<', '>', ':', '\"', '|', '?' dhe '*' nuk lejohen.", -"Your storage is full, files can not be updated or synced anymore!" => "Hapsira juaj e arkivimit është plot, skedarët nuk mund të përditësohen ose sinkronizohen!", -"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.", +"Pending" => "Në vijim", +"Error moving file" => "Gabim lëvizjen dokumentave", "Error" => "Gabim", "Name" => "Emri", "Size" => "Madhësia", "Modified" => "Ndryshuar", +"_%n folder_::_%n folders_" => array("%n dosje","%n dosje"), +"_%n file_::_%n files_" => array("%n skedar","%n skedarë"), +"_Uploading %n file_::_Uploading %n files_" => array("Po ngarkoj %n skedar","Po ngarkoj %n skedarë"), +"Your storage is full, files can not be updated or synced anymore!" => "Hapsira juaj e arkivimit është plot, skedarët nuk mund të përditësohen ose sinkronizohen!", +"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.", +"{dirs} and {files}" => "{dirs} dhe {files}", "%s could not be renamed" => "Nuk është i mundur riemërtimi i %s", -"Upload" => "Ngarko", "File handling" => "Trajtimi i Skedarëve", "Maximum upload size" => "Madhësia maksimale e nagarkimit", "max. possible: " => "maks i mundshëm", @@ -52,6 +50,7 @@ $TRANSLATIONS = array( "Save" => "Ruaj", "New" => "E re", "Text file" => "Skedar tekst", +"New folder" => "Dosje e're", "Folder" => "Dosje", "From link" => "Nga lidhja", "Deleted files" => "Skedarë të fshirë ", @@ -62,7 +61,6 @@ $TRANSLATIONS = array( "Upload too large" => "Ngarkimi shumë i madh", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Skedarët që po mundoheni të ngarkoni e tejkalojnë madhësinë maksimale të lejuar nga serveri.", "Files are being scanned, please wait." => "Skanerizimi i skedarit në proces. Ju lutem prisni.", -"Current scanning" => "Skanimi aktual", -"Upgrading filesystem cache..." => "Përditësimi i cache-se së sistemit në procesim..." +"Current scanning" => "Skanimi aktual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/sr.php b/apps/files/l10n/sr.php index e383b66e07..4cb50b318c 100644 --- a/apps/files/l10n/sr.php +++ b/apps/files/l10n/sr.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Не могу да преместим %s – датотека с овим именом већ постоји", "Could not move %s" => "Не могу да преместим %s", "File name cannot be empty." => "Име датотеке не може бити празно.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неисправан назив. Следећи знакови нису дозвољени: \\, /, <, >, :, \", |, ? и *.", "No file was uploaded. Unknown error" => "Ниједна датотека није отпремљена услед непознате грешке", "There is no error, the file uploaded with success" => "Није дошло до грешке. Датотека је успешно отпремљена.", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "Отпремљена датотека прелази смерницу upload_max_filesize у датотеци php.ini:", @@ -14,29 +15,23 @@ $TRANSLATIONS = array( "Not enough storage available" => "Нема довољно простора", "Invalid directory." => "неисправна фасцикла.", "Files" => "Датотеке", -"Not enough space available" => "Нема довољно простора", "Upload cancelled." => "Отпремање је прекинуто.", "File upload is in progress. Leaving the page now will cancel the upload." => "Отпремање датотеке је у току. Ако сада напустите страницу, прекинућете отпремање.", "{new_name} already exists" => "{new_name} већ постоји", "Share" => "Дели", "Delete permanently" => "Обриши за стално", "Rename" => "Преименуј", -"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("","",""), -"'.' is an invalid file name." => "Датотека „.“ је неисправног имена.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неисправан назив. Следећи знакови нису дозвољени: \\, /, <, >, :, \", |, ? и *.", -"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." => "Припремам преузимање. Ово може да потраје ако су датотеке велике.", +"Pending" => "На чекању", "Error" => "Грешка", "Name" => "Име", "Size" => "Величина", "Modified" => "Измењено", -"Upload" => "Отпреми", +"_%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}%)", "File handling" => "Управљање датотекама", "Maximum upload size" => "Највећа величина датотеке", "max. possible: " => "највећа величина:", @@ -57,7 +52,6 @@ $TRANSLATIONS = array( "Upload too large" => "Датотека је превелика", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Датотеке које желите да отпремите прелазе ограничење у величини.", "Files are being scanned, please wait." => "Скенирам датотеке…", -"Current scanning" => "Тренутно скенирање", -"Upgrading filesystem cache..." => "Дограђујем кеш система датотека…" +"Current scanning" => "Тренутно скенирање" ); $PLURAL_FORMS = "nplurals=3; 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/sr@latin.php b/apps/files/l10n/sr@latin.php index 13ce5ec8b3..8ec42c56c7 100644 --- a/apps/files/l10n/sr@latin.php +++ b/apps/files/l10n/sr@latin.php @@ -7,14 +7,14 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Nedostaje privremena fascikla", "Files" => "Fajlovi", "Share" => "Podeli", -"_%n folder_::_%n folders_" => array("","",""), -"_%n file_::_%n files_" => array("","",""), -"_Uploading %n file_::_Uploading %n files_" => array("","",""), +"Rename" => "Preimenij", "Error" => "Greška", "Name" => "Ime", "Size" => "Veličina", "Modified" => "Zadnja izmena", -"Upload" => "Pošalji", +"_%n folder_::_%n folders_" => array("","",""), +"_%n file_::_%n files_" => array("","",""), +"_Uploading %n file_::_Uploading %n files_" => array("","",""), "Maximum upload size" => "Maksimalna veličina pošiljke", "Save" => "Snimi", "Nothing in here. Upload something!" => "Ovde nema ničeg. Pošaljite nešto!", diff --git a/apps/files/l10n/su.php b/apps/files/l10n/su.php new file mode 100644 index 0000000000..70ab6572ba --- /dev/null +++ b/apps/files/l10n/su.php @@ -0,0 +1,7 @@ + array(""), +"_%n file_::_%n files_" => array(""), +"_Uploading %n file_::_Uploading %n files_" => array("") +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/sv.php b/apps/files/l10n/sv.php index 9e1b8110d4..8908be66d3 100644 --- a/apps/files/l10n/sv.php +++ b/apps/files/l10n/sv.php @@ -3,13 +3,15 @@ $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.", -"File name must not contain \"/\". Please choose a different name." => "Filnamnet får ej innehålla \"/\". Välj ett annat namn.", +"\"%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.", -"Folder name must not contain \"/\". Please choose a different name." => "Katalog namnet får ej innehålla \"/\". Välj ett annat namn.", "Error when creating the folder" => "Fel under skapande utav en katalog", "Unable to set upload directory." => "Kan inte sätta mapp för uppladdning.", "Invalid Token" => "Ogiltig token", @@ -22,48 +24,45 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "En temporär mapp saknas", "Failed to write to disk" => "Misslyckades spara till disk", "Not enough storage available" => "Inte tillräckligt med lagringsutrymme tillgängligt", -"Upload failed. Could not get file info." => "Uppladdning misslyckades. Gick inte att hämta filinformation.", "Upload failed. Could not find uploaded file" => "Uppladdning misslyckades. Kunde inte hitta den uppladdade filen", +"Upload failed. Could not get file info." => "Uppladdning misslyckades. Gick inte att hämta filinformation.", "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.", -"Not enough space available" => "Inte tillräckligt med utrymme tillgängligt", +"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.", "URL cannot be empty" => "URL kan ej vara tomt", -"In the home folder 'Shared' is a reserved filename" => "I hemma katalogen 'Delat' är ett reserverat filnamn", "{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", +"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.", "Pending" => "Väntar", +"Error moving file" => "Fel uppstod vid flyttning av fil", +"Error" => "Fel", "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.", +"Name" => "Namn", +"Size" => "Storlek", +"Modified" => "Ändrad", "_%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"), -"'.' is an invalid file name." => "'.' är ett ogiltigt filnamn.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ogiltigt namn, '\\', '/', '<', '>', ':', '\"', '|', '?' och '*' är inte tillåtet.", +"\"{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", -"Invalid folder name. Usage of 'Shared' is reserved." => "Ogiltigt mappnamn. Användande av 'Shared' är reserverat av ownCloud", +"{dirs} and {files}" => "{dirs} och {files}", "%s could not be renamed" => "%s kunde inte namnändras", -"Upload" => "Ladda upp", +"Upload (max. %s)" => "Ladda upp (max. %s)", "File handling" => "Filhantering", "Maximum upload size" => "Maximal storlek att ladda upp", "max. possible: " => "max. möjligt:", @@ -73,6 +72,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", @@ -86,7 +86,6 @@ $TRANSLATIONS = array( "Upload too large" => "För stor uppladdning", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filerna du försöker ladda upp överstiger den maximala storleken för filöverföringar på servern.", "Files are being scanned, please wait." => "Filer skannas, var god vänta", -"Current scanning" => "Aktuell skanning", -"Upgrading filesystem cache..." => "Uppgraderar filsystemets cache..." +"Current scanning" => "Aktuell skanning" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ta_IN.php b/apps/files/l10n/ta_IN.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/ta_IN.php @@ -0,0 +1,7 @@ + array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/ta_LK.php b/apps/files/l10n/ta_LK.php index f91a74ee9b..bba3ce9942 100644 --- a/apps/files/l10n/ta_LK.php +++ b/apps/files/l10n/ta_LK.php @@ -1,5 +1,6 @@ ', ':', '\"', '|', '?' and '*' are not allowed." => "செல்லுபடியற்ற பெயர்,'\\', '/', '<', '>', ':', '\"', '|', '?' மற்றும் '*' ஆகியன அனுமதிக்கப்படமாட்டாது.", "No file was uploaded. Unknown error" => "ஒரு கோப்பும் பதிவேற்றப்படவில்லை. அறியப்படாத வழு", "There is no error, the file uploaded with success" => "இங்கு வழு இல்லை, கோப்பு வெற்றிகரமாக பதிவேற்றப்பட்டது", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" => "பதிவேற்றப்பட்ட கோப்பானது HTML படிவத்தில் குறிப்பிடப்பட்டுள்ள MAX_FILE_SIZE directive ஐ விட கூடியது", @@ -14,17 +15,13 @@ $TRANSLATIONS = array( "Share" => "பகிர்வு", "Rename" => "பெயர்மாற்றம்", "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("",""), -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "செல்லுபடியற்ற பெயர்,'\\', '/', '<', '>', ':', '\"', '|', '?' மற்றும் '*' ஆகியன அனுமதிக்கப்படமாட்டாது.", "Error" => "வழு", "Name" => "பெயர்", "Size" => "அளவு", "Modified" => "மாற்றப்பட்டது", -"Upload" => "பதிவேற்றுக", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "File handling" => "கோப்பு கையாளுதல்", "Maximum upload size" => "பதிவேற்றக்கூடிய ஆகக்கூடிய அளவு ", "max. possible: " => "ஆகக் கூடியது:", diff --git a/apps/files/l10n/te.php b/apps/files/l10n/te.php index 155e4b5c20..0cf230fd55 100644 --- a/apps/files/l10n/te.php +++ b/apps/files/l10n/te.php @@ -1,12 +1,12 @@ "శాశ్వతంగా తొలగించు", -"_%n folder_::_%n folders_" => array("",""), -"_%n file_::_%n files_" => array("",""), -"_Uploading %n file_::_Uploading %n files_" => array("",""), "Error" => "పొరపాటు", "Name" => "పేరు", "Size" => "పరిమాణం", +"_%n folder_::_%n folders_" => array("",""), +"_%n file_::_%n files_" => array("",""), +"_Uploading %n file_::_Uploading %n files_" => array("",""), "Save" => "భద్రపరచు", "New folder" => "కొత్త సంచయం", "Folder" => "సంచయం", diff --git a/apps/files/l10n/th_TH.php b/apps/files/l10n/th_TH.php index 38a67c5067..6371447110 100644 --- a/apps/files/l10n/th_TH.php +++ b/apps/files/l10n/th_TH.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "ไม่สามารถย้าย %s ได้ - ไฟล์ที่ใช้ชื่อนี้มีอยู่แล้ว", "Could not move %s" => "ไม่สามารถย้าย %s ได้", "File name cannot be empty." => "ชื่อไฟล์ไม่สามารถเว้นว่างได้", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "ชื่อที่ใช้ไม่ถูกต้อง, '\\', '/', '<', '>', ':', '\"', '|', '?' และ '*' ไม่ได้รับอนุญาตให้ใช้งานได้", "No file was uploaded. Unknown error" => "ยังไม่มีไฟล์ใดที่ถูกอัพโหลด เกิดข้อผิดพลาดที่ไม่ทราบสาเหตุ", "There is no error, the file uploaded with success" => "ไม่พบข้อผิดพลาดใดๆ, ไฟล์ถูกอัพโหลดเรียบร้อยแล้ว", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "ขนาดไฟล์ที่อัพโหลดมีขนาดเกิน upload_max_filesize ที่ระบุไว้ใน php.ini", @@ -14,28 +15,22 @@ $TRANSLATIONS = array( "Not enough storage available" => "เหลือพื้นที่ไม่เพียงสำหรับใช้งาน", "Invalid directory." => "ไดเร็กทอรี่ไม่ถูกต้อง", "Files" => "ไฟล์", -"Not enough space available" => "มีพื้นที่เหลือไม่เพียงพอ", "Upload cancelled." => "การอัพโหลดถูกยกเลิก", "File upload is in progress. Leaving the page now will cancel the upload." => "การอัพโหลดไฟล์กำลังอยู่ในระหว่างดำเนินการ การออกจากหน้าเว็บนี้จะทำให้การอัพโหลดถูกยกเลิก", "{new_name} already exists" => "{new_name} มีอยู่แล้วในระบบ", "Share" => "แชร์", "Rename" => "เปลี่ยนชื่อ", -"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(""), -"'.' is an invalid file name." => "'.' เป็นชื่อไฟล์ที่ไม่ถูกต้อง", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "ชื่อที่ใช้ไม่ถูกต้อง, '\\', '/', '<', '>', ':', '\"', '|', '?' และ '*' ไม่ได้รับอนุญาตให้ใช้งานได้", -"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." => "กำลังเตรียมดาวน์โหลดข้อมูล หากไฟล์มีขนาดใหญ่ อาจใช้เวลาสักครู่", +"Pending" => "อยู่ระหว่างดำเนินการ", "Error" => "ข้อผิดพลาด", "Name" => "ชื่อ", "Size" => "ขนาด", "Modified" => "แก้ไขแล้ว", -"Upload" => "อัพโหลด", +"_%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}%)", "File handling" => "การจัดกาไฟล์", "Maximum upload size" => "ขนาดไฟล์สูงสุดที่อัพโหลดได้", "max. possible: " => "จำนวนสูงสุดที่สามารถทำได้: ", @@ -46,6 +41,7 @@ $TRANSLATIONS = array( "Save" => "บันทึก", "New" => "อัพโหลดไฟล์ใหม่", "Text file" => "ไฟล์ข้อความ", +"New folder" => "โฟลเดอร์ใหม่", "Folder" => "แฟ้มเอกสาร", "From link" => "จากลิงก์", "Cancel upload" => "ยกเลิกการอัพโหลด", @@ -55,7 +51,6 @@ $TRANSLATIONS = array( "Upload too large" => "ไฟล์ที่อัพโหลดมีขนาดใหญ่เกินไป", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "ไฟล์ที่คุณพยายามที่จะอัพโหลดมีขนาดเกินกว่าขนาดสูงสุดที่กำหนดไว้ให้อัพโหลดได้สำหรับเซิร์ฟเวอร์นี้", "Files are being scanned, please wait." => "ไฟล์กำลังอยู่ระหว่างการสแกน, กรุณารอสักครู่.", -"Current scanning" => "ไฟล์ที่กำลังสแกนอยู่ขณะนี้", -"Upgrading filesystem cache..." => "กำลังอัพเกรดหน่วยความจำแคชของระบบไฟล์..." +"Current scanning" => "ไฟล์ที่กำลังสแกนอยู่ขณะนี้" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/tr.php b/apps/files/l10n/tr.php index 90b16922a7..a62e0f3eb6 100644 --- a/apps/files/l10n/tr.php +++ b/apps/files/l10n/tr.php @@ -1,16 +1,17 @@ "%s taşınamadı - Bu isimde dosya zaten var", +"Could not move %s - File with this name already exists" => "%s taşınamadı. Bu isimde dosya zaten mevcut", "Could not move %s" => "%s taşınamadı", "File name cannot be empty." => "Dosya adı boş olamaz.", -"File name must not contain \"/\". Please choose a different name." => "Dosya adı \"/\" içermemelidir. Lütfen farklı bir isim seçin.", +"\"%s\" is an invalid file name." => "'%s' geçersiz bir dosya adı.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Geçersiz isim, '\\', '/', '<', '>', ':', '\"', '|', '?' ve '*' karakterlerine izin verilmemektedir.", +"The target folder has been moved or deleted." => "Hedef klasör taşındı veya silindi.", "The name %s is already used in the folder %s. Please choose a different name." => "%s ismi zaten %s klasöründe kullanılıyor. Lütfen farklı bir isim seçin.", "Not a valid source" => "Geçerli bir kaynak değil", "Server is not allowed to open URLs, please check the server configuration" => "Sunucunun adresleri açma izi yok, lütfen sunucu yapılandırmasını denetleyin", "Error while downloading %s to %s" => "%s, %s içine indirilirken hata", "Error when creating the file" => "Dosya oluşturulurken hata", "Folder name cannot be empty." => "Klasör adı boş olamaz.", -"Folder name must not contain \"/\". Please choose a different name." => "Klasör adı \"/\" içermemelidir. Lütfen farklı bir isim seçin.", "Error when creating the folder" => "Klasör oluşturulurken hata", "Unable to set upload directory." => "Yükleme dizini tanımlanamadı.", "Invalid Token" => "Geçersiz Simge", @@ -23,49 +24,46 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Geçici dizin eksik", "Failed to write to disk" => "Diske yazılamadı", "Not enough storage available" => "Yeterli disk alanı yok", -"Upload failed. Could not get file info." => "Yükleme başarısız. Dosya bilgisi alınamadı.", "Upload failed. Could not find uploaded file" => "Yükleme başarısız. Yüklenen dosya bulunamadı", +"Upload failed. Could not get file info." => "Yükleme başarısız. Dosya bilgisi alınamadı.", "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", -"Not enough space available" => "Yeterli disk alanı yok", +"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ı.", "File upload is in progress. Leaving the page now will cancel the upload." => "Dosya yükleme işlemi sürüyor. Şimdi sayfadan ayrılırsanız işleminiz iptal olur.", "URL cannot be empty" => "URL boş olamaz", -"In the home folder 'Shared' is a reserved filename" => "Ev klasöründeki 'Paylaşılan', ayrılmış bir dosya adıdır", "{new_name} already exists" => "{new_name} zaten mevcut", "Could not create file" => "Dosya oluşturulamadı", "Could not create folder" => "Klasör oluşturulamadı", "Error fetching URL" => "Adres getirilirken hata", "Share" => "Paylaş", "Delete permanently" => "Kalıcı olarak sil", -"Rename" => "İsim değiştir.", +"Rename" => "Yeniden adlandır", +"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.", "Pending" => "Bekliyor", +"Error moving file." => "Dosya taşıma hatası.", +"Error moving file" => "Dosya taşıma hatası", +"Error" => "Hata", "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.", +"Name" => "İsim", +"Size" => "Boyut", +"Modified" => "Değiştirilme", "_%n folder_::_%n folders_" => array("%n dizin","%n dizin"), "_%n file_::_%n files_" => array("%n dosya","%n dosya"), -"{dirs} and {files}" => "{dirs} ve {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n dosya yükleniyor","%n dosya yükleniyor"), -"'.' is an invalid file name." => "'.' geçersiz bir dosya adı.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Geçersiz isim, '\\', '/', '<', '>', ':', '\"', '|', '?' ve '*' karakterlerine izin verilmemektedir.", +"\"{name}\" is an invalid file name." => "\"{name}\" geçersiz bir dosya adı.", "Your storage is full, files can not be updated or synced anymore!" => "Depolama alanınız dolu, artık dosyalar güncellenmeyecek veya eşitlenmeyecek.", "Your storage is almost full ({usedSpacePercent}%)" => "Depolama alanınız neredeyse dolu ({usedSpacePercent}%)", "Encryption App is enabled but your keys are not initialized, please log-out and log-in again" => "Şifreleme Uygulaması etkin ancak anahtarlarınız başlatılmamış. Lütfen oturumu kapatıp yeniden açın", "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.", +"{dirs} and {files}" => "{dirs} ve {files}", "%s could not be renamed" => "%s yeniden adlandırılamadı", -"Upload" => "Yükle", +"Upload (max. %s)" => "Yükle (azami: %s)", "File handling" => "Dosya işlemleri", "Maximum upload size" => "Maksimum yükleme boyutu", "max. possible: " => "mümkün olan en fazla: ", @@ -89,7 +87,6 @@ $TRANSLATIONS = array( "Upload too large" => "Yükleme çok büyük", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Yüklemeye çalıştığınız dosyalar bu sunucudaki maksimum yükleme boyutunu aşıyor.", "Files are being scanned, please wait." => "Dosyalar taranıyor, lütfen bekleyin.", -"Current scanning" => "Güncel tarama", -"Upgrading filesystem cache..." => "Sistem dosyası önbelleği güncelleniyor" +"Current scanning" => "Güncel tarama" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files/l10n/ug.php b/apps/files/l10n/ug.php index 45458c51af..446852368f 100644 --- a/apps/files/l10n/ug.php +++ b/apps/files/l10n/ug.php @@ -7,7 +7,6 @@ $TRANSLATIONS = array( "Failed to write to disk" => "دىسكىغا يازالمىدى", "Not enough storage available" => "يېتەرلىك ساقلاش بوشلۇقى يوق", "Files" => "ھۆججەتلەر", -"Not enough space available" => "يېتەرلىك بوشلۇق يوق", "Upload cancelled." => "يۈكلەشتىن ۋاز كەچتى.", "File upload is in progress. Leaving the page now will cancel the upload." => "ھۆججەت يۈكلەش مەشغۇلاتى ئېلىپ بېرىلىۋاتىدۇ. Leaving the page now will cancel the upload.", "{new_name} already exists" => "{new_name} مەۋجۇت", @@ -15,15 +14,13 @@ $TRANSLATIONS = array( "Delete permanently" => "مەڭگۈلۈك ئۆچۈر", "Rename" => "ئات ئۆزگەرت", "Pending" => "كۈتۈۋاتىدۇ", -"undo" => "يېنىۋال", -"_%n folder_::_%n folders_" => array(""), -"_%n file_::_%n files_" => array(""), -"_Uploading %n file_::_Uploading %n files_" => array(""), "Error" => "خاتالىق", "Name" => "ئاتى", "Size" => "چوڭلۇقى", "Modified" => "ئۆزگەرتكەن", -"Upload" => "يۈكلە", +"_%n folder_::_%n folders_" => array(""), +"_%n file_::_%n files_" => array(""), +"_Uploading %n file_::_Uploading %n files_" => array(""), "Save" => "ساقلا", "New" => "يېڭى", "Text file" => "تېكىست ھۆججەت", @@ -34,7 +31,6 @@ $TRANSLATIONS = array( "Nothing in here. Upload something!" => "بۇ جايدا ھېچنېمە يوق. Upload something!", "Download" => "چۈشۈر", "Delete" => "ئۆچۈر", -"Upload too large" => "يۈكلەندىغىنى بەك چوڭ", -"Upgrading filesystem cache..." => "ھۆججەت سىستېما غەملىكىنى يۈكسەلدۈرۈۋاتىدۇ…" +"Upload too large" => "يۈكلەندىغىنى بەك چوڭ" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/uk.php b/apps/files/l10n/uk.php index 1e37d3d77d..8fb578016c 100644 --- a/apps/files/l10n/uk.php +++ b/apps/files/l10n/uk.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Не вдалося перемістити %s - Файл з таким ім'ям вже існує", "Could not move %s" => "Не вдалося перемістити %s", "File name cannot be empty." => " Ім'я файлу не може бути порожнім.", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Невірне ім'я, '\\', '/', '<', '>', ':', '\"', '|', '?' та '*' не дозволені.", "Folder name cannot be empty." => "Ім'я теки не може бути порожнім.", "Unable to set upload directory." => "Не вдалося встановити каталог завантаження.", "No file was uploaded. Unknown error" => "Не завантажено жодного файлу. Невідома помилка", @@ -16,7 +17,6 @@ $TRANSLATIONS = array( "Not enough storage available" => "Місця більше немає", "Invalid directory." => "Невірний каталог.", "Files" => "Файли", -"Not enough space available" => "Місця більше немає", "Upload cancelled." => "Завантаження перервано.", "File upload is in progress. Leaving the page now will cancel the upload." => "Виконується завантаження файлу. Закриття цієї сторінки приведе до відміни завантаження.", "URL cannot be empty" => "URL не може бути порожнім", @@ -26,25 +26,20 @@ $TRANSLATIONS = array( "Share" => "Поділитися", "Delete permanently" => "Видалити назавжди", "Rename" => "Перейменувати", -"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("","",""), -"'.' is an invalid file name." => "'.' це невірне ім'я файлу.", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Невірне ім'я, '\\', '/', '<', '>', ':', '\"', '|', '?' та '*' не дозволені.", -"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." => "Ваше завантаження готується. Це може зайняти деякий час, якщо файли завеликі.", +"Pending" => "Очікування", "Error moving file" => "Помилка переміщення файлу", "Error" => "Помилка", +"Could not rename file" => "Неможливо перейменувати файл", "Name" => "Ім'я", "Size" => "Розмір", "Modified" => "Змінено", +"_%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}%)", "%s could not be renamed" => "%s не може бути перейменований", -"Upload" => "Вивантажити", "File handling" => "Робота з файлами", "Maximum upload size" => "Максимальний розмір відвантажень", "max. possible: " => "макс.можливе:", @@ -66,7 +61,6 @@ $TRANSLATIONS = array( "Upload too large" => "Файл занадто великий", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Файли,що ви намагаєтесь відвантажити перевищують максимальний дозволений розмір файлів на цьому сервері.", "Files are being scanned, please wait." => "Файли скануються, зачекайте, будь-ласка.", -"Current scanning" => "Поточне сканування", -"Upgrading filesystem cache..." => "Оновлення кеша файлової системи..." +"Current scanning" => "Поточне сканування" ); $PLURAL_FORMS = "nplurals=3; 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/ur_PK.php b/apps/files/l10n/ur_PK.php index 3e13a7f516..b9548acde9 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 8236d5e7ef..c14f1b7ea0 100644 --- a/apps/files/l10n/vi.php +++ b/apps/files/l10n/vi.php @@ -3,6 +3,16 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "Không thể di chuyển %s - Đã có tên tập tin này trên hệ thống", "Could not move %s" => "Không thể di chuyển %s", "File name cannot be empty." => "Tên file không được rỗng", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Tên không hợp lệ, '\\', '/', '<', '>', ':', '\"', '|', '?' và '*' thì không được phép dùng.", +"The name %s is already used in the folder %s. Please choose a different name." => "Tên %s đã được sử dụng trong thư mục %s. Hãy chọn tên khác.", +"Not a valid source" => "Nguồn không hợp lệ", +"Server is not allowed to open URLs, please check the server configuration" => "Server cấm mở URLs, vui lòng kiểm tra lại cấu hình server", +"Error while downloading %s to %s" => "Lỗi trong trong quá trình tải %s từ %s", +"Error when creating the file" => "Lỗi khi tạo file", +"Folder name cannot be empty." => "Tên thư mục không thể để trống", +"Error when creating the folder" => "Lỗi khi tạo thư mục", +"Unable to set upload directory." => "Không thể thiết lập thư mục tải lên.", +"Invalid Token" => "Xác thực không hợp lệ", "No file was uploaded. Unknown error" => "Không có tập tin nào được tải lên. Lỗi không xác định", "There is no error, the file uploaded with success" => "Không có lỗi, các tập tin đã được tải lên thành công", "The uploaded file exceeds the upload_max_filesize directive in php.ini: " => "The uploaded file exceeds the upload_max_filesize directive in php.ini: ", @@ -12,31 +22,39 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "Không tìm thấy thư mục tạm", "Failed to write to disk" => "Không thể ghi ", "Not enough storage available" => "Không đủ không gian lưu trữ", +"Upload failed. Could not find uploaded file" => "Tải lên thất bại. Không thể tìm thấy tập tin được tải lên", +"Upload failed. Could not get file info." => "Tải lên thất bại. Không thể có được thông tin tập tin.", "Invalid directory." => "Thư mục không hợp lệ", "Files" => "Tập tin", -"Not enough space available" => "Không đủ chỗ trống cần thiết", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "không thể tải {filename} lên do nó là một thư mục hoặc có kích thước bằng 0 byte", "Upload cancelled." => "Hủy tải lên", +"Could not get result from server." => "Không thể nhận được kết quả từ máy chủ.", "File upload is in progress. Leaving the page now will cancel the upload." => "Tập tin tải lên đang được xử lý. Nếu bạn rời khỏi trang bây giờ sẽ hủy quá trình này.", +"URL cannot be empty" => "URL không thể để trống", "{new_name} already exists" => "{new_name} đã tồn tại", +"Could not create file" => "Không thể tạo file", +"Could not create folder" => "Không thể tạo thư mục", "Share" => "Chia sẻ", "Delete permanently" => "Xóa vĩnh vễn", "Rename" => "Sửa tên", -"Pending" => "Đang chờ", -"replaced {new_name} with {old_name}" => "đã thay thế {new_name} bằng {old_name}", -"undo" => "lùi lại", -"_%n folder_::_%n folders_" => array(""), -"_%n file_::_%n files_" => array(""), -"_Uploading %n file_::_Uploading %n files_" => array(""), -"'.' is an invalid file name." => "'.' là một tên file không hợp lệ", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Tên không hợp lệ, '\\', '/', '<', '>', ':', '\"', '|', '?' và '*' thì không được phép dùng.", -"Your storage is full, files can not be updated or synced anymore!" => "Your storage is full, files can not be updated or synced anymore!", -"Your storage is almost full ({usedSpacePercent}%)" => "Your storage is almost full ({usedSpacePercent}%)", "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.", +"Pending" => "Đang chờ", +"Error moving file" => "Lỗi di chuyển tập tin", "Error" => "Lỗi", +"Could not rename file" => "Không thể đổi tên file", +"Error deleting file." => "Lỗi xóa file,", "Name" => "Tên", "Size" => "Kích cỡ", "Modified" => "Thay đổi", -"Upload" => "Tải lên", +"_%n folder_::_%n folders_" => array("%n thư mục"), +"_%n file_::_%n files_" => array("%n tập tin"), +"_Uploading %n file_::_Uploading %n files_" => array("Đang tải lên %n tập tin"), +"Your storage is full, files can not be updated or synced anymore!" => "Your storage is full, files can not be updated or synced anymore!", +"Your storage is almost full ({usedSpacePercent}%)" => "Your storage is almost full ({usedSpacePercent}%)", +"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.", +"{dirs} and {files}" => "{dirs} và {files}", +"%s could not be renamed" => "%s không thể đổi tên", "File handling" => "Xử lý tập tin", "Maximum upload size" => "Kích thước tối đa ", "max. possible: " => "tối đa cho phép:", @@ -45,20 +63,21 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 là không giới hạn", "Maximum input size for ZIP files" => "Kích thước tối đa cho các tập tin ZIP", "Save" => "Lưu", -"New" => "Mới", +"New" => "Tạo mới", +"New text file" => "File text mới", "Text file" => "Tập tin văn bản", "New folder" => "Tạo thư mục", "Folder" => "Thư mục", "From link" => "Từ liên kết", "Deleted files" => "File đã bị xóa", "Cancel upload" => "Hủy upload", +"You don’t have permission to upload or create files here" => "Bạn không có quyền upload hoặc tạo files ở đây", "Nothing in here. Upload something!" => "Không có gì ở đây .Hãy tải lên một cái gì đó !", "Download" => "Tải về", "Delete" => "Xóa", "Upload too large" => "Tập tin tải lên quá lớn", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Các tập tin bạn đang tải lên vượt quá kích thước tối đa cho phép trên máy chủ .", "Files are being scanned, please wait." => "Tập tin đang được quét ,vui lòng chờ.", -"Current scanning" => "Hiện tại đang quét", -"Upgrading filesystem cache..." => "Đang nâng cấp bộ nhớ đệm cho tập tin hệ thống..." +"Current scanning" => "Hiện tại đang quét" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/zh_CN.php b/apps/files/l10n/zh_CN.php index effcb0225c..7f0183e920 100644 --- a/apps/files/l10n/zh_CN.php +++ b/apps/files/l10n/zh_CN.php @@ -3,6 +3,16 @@ $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网址,请检查服务器配置", +"Error while downloading %s to %s" => "当下载 %s 到 %s 时出错", +"Error when creating the file" => "当创建文件是出错", +"Folder name cannot be empty." => "文件夹名称不能为空", +"Error when creating the folder" => "创建文件夹出错", "Unable to set upload directory." => "无法设置上传文件夹。", "Invalid Token" => "无效密匙", "No file was uploaded. Unknown error" => "没有文件被上传。未知错误", @@ -14,32 +24,46 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "缺少临时目录", "Failed to write to disk" => "写入磁盘失败", "Not enough storage available" => "没有足够的存储空间", +"Upload failed. Could not find uploaded file" => "上传失败。不能发现上传的文件", +"Upload failed. Could not get file info." => "上传失败。不能获取文件信息。", "Invalid directory." => "无效文件夹。", "Files" => "文件", -"Not enough space available" => "没有足够可用空间", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "不能上传文件 {filename} ,由于它是一个目录或者为0字节", +"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." => "文件正在上传中。现在离开此页会导致上传动作被取消。", +"URL cannot be empty" => "URL不能为空", "{new_name} already exists" => "{new_name} 已存在", +"Could not create file" => "不能创建文件", +"Could not create folder" => "不能创建文件夹", +"Error fetching URL" => "获取URL出错", "Share" => "分享", "Delete permanently" => "永久删除", "Rename" => "重命名", -"Pending" => "等待", -"replaced {new_name} with {old_name}" => "已将 {old_name}替换成 {new_name}", -"undo" => "撤销", -"_%n folder_::_%n folders_" => array("%n 文件夹"), -"_%n file_::_%n files_" => array("%n个文件"), -"_Uploading %n file_::_Uploading %n files_" => array(""), -"'.' is an invalid file name." => "'.' 是一个无效的文件名。", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "无效名称,'\\', '/', '<', '>', ':', '\"', '|', '?' 和 '*' 不被允许使用。", -"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." => "下载正在准备中。如果文件较大可能会花费一些时间。", +"Pending" => "等待", +"Error moving file." => "移动文件出错。", +"Error moving file" => "移动文件错误", "Error" => "错误", +"Could not rename file" => "不能重命名文件", +"Error deleting file." => "删除文件出错。", "Name" => "名称", "Size" => "大小", "Modified" => "修改日期", +"_%n folder_::_%n folders_" => array("%n 文件夹"), +"_%n file_::_%n files_" => array("%n个文件"), +"_Uploading %n file_::_Uploading %n files_" => array("上传 %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." => "加密是被禁用的,但是您的文件还是被加密了。请到您的个人配置里设置文件加密选项。", +"{dirs} and {files}" => "{dirs} 和 {files}", "%s could not be renamed" => "%s 不能被重命名", -"Upload" => "上传", +"Upload (max. %s)" => "上传 (最大 %s)", "File handling" => "文件处理", "Maximum upload size" => "最大上传大小", "max. possible: " => "最大允许: ", @@ -49,19 +73,20 @@ $TRANSLATIONS = array( "Maximum input size for ZIP files" => "ZIP 文件的最大输入大小", "Save" => "保存", "New" => "新建", +"New text file" => "创建文本文件", "Text file" => "文本文件", "New folder" => "添加文件夹", "Folder" => "文件夹", "From link" => "来自链接", "Deleted files" => "已删除文件", "Cancel upload" => "取消上传", +"You don’t have permission to upload or create files here" => "您没有权限来上传湖州哦和创建文件", "Nothing in here. Upload something!" => "这里还什么都没有。上传些东西吧!", "Download" => "下载", "Delete" => "删除", "Upload too large" => "上传文件过大", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "您正尝试上传的文件超过了此服务器可以上传的最大容量限制", "Files are being scanned, please wait." => "文件正在被扫描,请稍候。", -"Current scanning" => "当前扫描", -"Upgrading filesystem cache..." => "正在更新文件系统缓存..." +"Current scanning" => "当前扫描" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/zh_HK.php b/apps/files/l10n/zh_HK.php index 4885500ce4..62a37f4040 100644 --- a/apps/files/l10n/zh_HK.php +++ b/apps/files/l10n/zh_HK.php @@ -2,13 +2,14 @@ $TRANSLATIONS = array( "Files" => "文件", "Share" => "分享", +"Error" => "錯誤", +"Name" => "名稱", +"Size" => "大小", "_%n folder_::_%n folders_" => array(""), "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), -"Error" => "錯誤", -"Name" => "名稱", -"Upload" => "上傳", "Save" => "儲存", +"New folder" => "新文件夾", "Download" => "下載", "Delete" => "刪除" ); diff --git a/apps/files/l10n/zh_TW.php b/apps/files/l10n/zh_TW.php index dd9cbfdf1a..7b4caf592a 100644 --- a/apps/files/l10n/zh_TW.php +++ b/apps/files/l10n/zh_TW.php @@ -3,13 +3,12 @@ $TRANSLATIONS = array( "Could not move %s - File with this name already exists" => "無法移動 %s ,同名的檔案已經存在", "Could not move %s" => "無法移動 %s", "File name cannot be empty." => "檔名不能為空", -"File name must not contain \"/\". Please choose a different name." => "檔名不能包含 \"/\" ,請選其他名字", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "檔名不合法,不允許 \\ / < > : \" | ? * 字元", "The name %s is already used in the folder %s. Please choose a different name." => "%s 已經被使用於資料夾 %s ,請換一個名字", "Not a valid source" => "不是有效的來源", "Error while downloading %s to %s" => "下載 %s 到 %s 失敗", "Error when creating the file" => "建立檔案失敗", "Folder name cannot be empty." => "資料夾名稱不能留空", -"Folder name must not contain \"/\". Please choose a different name." => "資料夾名稱不能包含 \"/\" ,請選其他名字", "Error when creating the folder" => "建立資料夾失敗", "Unable to set upload directory." => "無法設定上傳目錄", "Invalid Token" => "無效的 token", @@ -22,46 +21,39 @@ $TRANSLATIONS = array( "Missing a temporary folder" => "找不到暫存資料夾", "Failed to write to disk" => "寫入硬碟失敗", "Not enough storage available" => "儲存空間不足", -"Upload failed. Could not get file info." => "上傳失敗,無法取得檔案資訊", "Upload failed. Could not find uploaded file" => "上傳失敗,找不到上傳的檔案", +"Upload failed. Could not get file info." => "上傳失敗,無法取得檔案資訊", "Invalid directory." => "無效的資料夾", "Files" => "檔案", "Unable to upload {filename} as it is a directory or has 0 bytes" => "因為 {filename} 是個目錄或是大小為零,所以無法上傳", -"Not enough space available" => "沒有足夠的可用空間", "Upload cancelled." => "上傳已取消", "Could not get result from server." => "無法從伺服器取回結果", "File upload is in progress. Leaving the page now will cancel the upload." => "檔案上傳中,離開此頁面將會取消上傳。", "URL cannot be empty" => "URL 不能留空", -"In the home folder 'Shared' is a reserved filename" => "在家目錄中不能使用「共享」作為檔名", "{new_name} already exists" => "{new_name} 已經存在", "Could not create file" => "無法建立檔案", "Could not create folder" => "無法建立資料夾", "Share" => "分享", "Delete permanently" => "永久刪除", "Rename" => "重新命名", +"Your download is being prepared. This might take some time if the files are big." => "正在準備您的下載,若您的檔案較大,將會需要更多時間。", "Pending" => "等候中", +"Error moving file" => "移動檔案失敗", +"Error" => "錯誤", "Could not rename file" => "無法重新命名", -"replaced {new_name} with {old_name}" => "使用 {new_name} 取代 {old_name}", -"undo" => "復原", +"Name" => "名稱", +"Size" => "大小", +"Modified" => "修改時間", "_%n folder_::_%n folders_" => array("%n 個資料夾"), "_%n file_::_%n files_" => array("%n 個檔案"), -"{dirs} and {files}" => "{dirs} 和 {files}", "_Uploading %n file_::_Uploading %n files_" => array("%n 個檔案正在上傳"), -"'.' is an invalid file name." => "'.' 是不合法的檔名", -"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "檔名不合法,不允許 \\ / < > : \" | ? * 字元", "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" => "修改時間", +"{dirs} and {files}" => "{dirs} 和 {files}", "%s could not be renamed" => "無法重新命名 %s", -"Upload" => "上傳", "File handling" => "檔案處理", "Maximum upload size" => "上傳限制", "max. possible: " => "最大允許:", @@ -84,7 +76,6 @@ $TRANSLATIONS = array( "Upload too large" => "上傳過大", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "您試圖上傳的檔案大小超過伺服器的限制。", "Files are being scanned, please wait." => "正在掃描檔案,請稍等。", -"Current scanning" => "正在掃描", -"Upgrading filesystem cache..." => "正在升級檔案系統快取…" +"Current scanning" => "正在掃描" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/lib/app.php b/apps/files/lib/app.php index fea88faa92..ed4aa32c66 100644 --- a/apps/files/lib/app.php +++ b/apps/files/lib/app.php @@ -54,13 +54,8 @@ class App { 'data' => NULL ); - // rename to "/Shared" is denied - if( $dir === '/' and $newname === 'Shared' ) { - $result['data'] = array( - 'message' => $this->l10n->t("Invalid folder name. Usage of 'Shared' is reserved.") - ); // rename to non-existing folder is denied - } else if (!$this->view->file_exists($dir)) { + if (!$this->view->file_exists($dir)) { $result['data'] = array('message' => (string)$this->l10n->t( 'The target folder has been moved or deleted.', array($dir)), @@ -68,7 +63,7 @@ class App { ); // rename to existing file is denied } else if ($this->view->file_exists($dir . '/' . $newname)) { - + $result['data'] = array( 'message' => $this->l10n->t( "The name %s is already used in the folder %s. Please choose a different name.", @@ -77,32 +72,12 @@ class App { } else if ( // rename to "." is denied $newname !== '.' and - // rename of "/Shared" is denied - !($dir === '/' and $oldname === 'Shared') and // THEN try to rename $this->view->rename($dir . '/' . $oldname, $dir . '/' . $newname) ) { // 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 ac8a2ad320..0ae87d12fb 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -11,7 +11,7 @@ class Helper $l = new \OC_L10N('files'); $maxUploadFilesize = \OCP\Util::maxUploadFilesize($dir, $storageInfo['free']); $maxHumanFilesize = \OCP\Util::humanFileSize($maxUploadFilesize); - $maxHumanFilesize = $l->t('Upload') . ' max. ' . $maxHumanFilesize; + $maxHumanFilesize = $l->t('Upload (max. %s)', array($maxHumanFilesize)); return array('uploadMaxFilesize' => $maxUploadFilesize, 'maxHumanFilesize' => $maxHumanFilesize, @@ -19,97 +19,113 @@ 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']; - $absPath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir.'/'.$file['name']); + $icon = \OC_Helper::mimetypeIcon('dir'); + $absPath = $file->getPath(); $mount = \OC\Files\Filesystem::getMountManager()->find($absPath); if (!is_null($mount)) { $sid = $mount->getStorageId(); if (!is_null($sid)) { $sid = explode(':', $sid); if ($sid[0] === 'shared') { - return \OC_Helper::mimetypeIcon('dir-shared'); - } - if ($sid[0] !== 'local' and $sid[0] !== 'home') { - return \OC_Helper::mimetypeIcon('dir-external'); + $icon = \OC_Helper::mimetypeIcon('dir-shared'); + } elseif ($sid[0] !== 'local' and $sid[0] !== 'home') { + $icon = \OC_Helper::mimetypeIcon('dir-external'); } } } - return \OC_Helper::mimetypeIcon('dir'); + }else{ + $icon = \OC_Helper::mimetypeIcon($file->getMimetype()); } - if($file['isPreviewAvailable']) { - $pathForPreview = $file['directory'] . '/' . $file['name']; - return \OC_Helper::previewIcon($pathForPreview) . '&c=' . $file['etag']; - } - return \OC_Helper::mimetypeIcon($file['mimetype']); + return substr($icon, 0, -3) . 'svg'; } /** * Comparator function to sort files alphabetically and have * the directories appear first - * @param array $a file - * @param array $b file - * @return -1 if $a must come before $b, 1 otherwise + * + * @param \OCP\Files\FileInfo $a file + * @param \OCP\Files\FileInfo $b file + * @return int -1 if $a must come before $b, 1 otherwise */ public static function fileCmp($a, $b) { - if ($a['type'] === 'dir' and $b['type'] !== 'dir') { + $aType = $a->getType(); + $bType = $b->getType(); + if ($aType === 'dir' and $bType !== 'dir') { return -1; - } elseif ($a['type'] !== 'dir' and $b['type'] === 'dir') { + } elseif ($aType !== 'dir' and $bType === 'dir') { return 1; } else { - return strnatcasecmp($a['name'], $b['name']); + return strnatcasecmp($a->getName(), $b->getName()); } } /** - * 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 $i + * @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['parentId'] = $i['parent']; + $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']; + } + if (isset($i['is_share_mount_point'])) { + $entry['isShareMountPoint'] = $i['is_share_mount_point']; + } + 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 a5afd55fbc..5f7d3261d6 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 662177ac7e..79beccef3e 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 ed15e46a5a..42263c880a 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -1,26 +1,25 @@
- -
+
-
+
-
class="hidden">t('Nothing in here. Upload something!'))?>
+ - - - + - + +
class="hidden" id='headerName'> + class="hidden" id="headerSize">t('Size')); ?>class="hidden" id="headerDate"> +
@@ -111,7 +111,6 @@ - diff --git a/apps/files/templates/part.breadcrumb.php b/apps/files/templates/part.breadcrumb.php deleted file mode 100644 index 2a0df62276..0000000000 --- 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']); ?> - - - - - style="background-image:url()" - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - t('Upgrading filesystem cache...'));?> -
-
diff --git a/apps/files/tests/ajax_rename.php b/apps/files/tests/ajax_rename.php index a1a5c8983b..74ca1e4495 100644 --- a/apps/files/tests/ajax_rename.php +++ b/apps/files/tests/ajax_rename.php @@ -55,82 +55,6 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase { \OC\Files\Filesystem::tearDown(); } - /** - * @brief test rename of file/folder named "Shared" - */ - function testRenameSharedFolder() { - $dir = '/'; - $oldname = 'Shared'; - $newname = 'new_name'; - - $this->viewMock->expects($this->at(0)) - ->method('file_exists') - ->with('/') - ->will($this->returnValue(true)); - - $result = $this->files->rename($dir, $oldname, $newname); - $expected = array( - 'success' => false, - 'data' => array('message' => '%s could not be renamed') - ); - - $this->assertEquals($expected, $result); - } - - /** - * @brief test rename of file/folder named "Shared" - */ - function testRenameSharedFolderInSubdirectory() { - $dir = '/test'; - $oldname = 'Shared'; - $newname = 'new_name'; - - $this->viewMock->expects($this->at(0)) - ->method('file_exists') - ->with('/test') - ->will($this->returnValue(true)); - - $this->viewMock->expects($this->any()) - ->method('getFileInfo') - ->will($this->returnValue(array( - 'fileid' => 123, - 'type' => 'dir', - 'mimetype' => 'httpd/unix-directory', - '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(\OC_Helper::mimetypeIcon('dir'), $result['data']['icon']); - $this->assertFalse($result['data']['isPreviewAvailable']); - } - - /** - * @brief test rename of file/folder to "Shared" - */ - function testRenameFolderToShared() { - $dir = '/'; - $oldname = 'oldname'; - $newname = 'Shared'; - - $result = $this->files->rename($dir, $oldname, $newname); - $expected = array( - 'success' => false, - 'data' => array('message' => "Invalid folder name. Usage of 'Shared' is reserved.") - ); - - $this->assertEquals($expected, $result); - } - /** * @brief test rename of file/folder */ @@ -146,27 +70,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']); - $this->assertEquals(\OC_Helper::mimetypeIcon('dir'), $result['data']['icon']); - $this->assertFalse($result['data']['isPreviewAvailable']); + $icon = \OC_Helper::mimetypeIcon('dir'); + $icon = substr($icon, 0, -3) . 'svg'; + $this->assertEquals($icon, $result['data']['icon']); } /** diff --git a/apps/files/tests/js/breadcrumbSpec.js b/apps/files/tests/js/breadcrumbSpec.js new file mode 100644 index 0000000000..1bfe5308a2 --- /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/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js new file mode 100644 index 0000000000..2b4341ef1c --- /dev/null +++ b/apps/files/tests/js/fileUploadSpec.js @@ -0,0 +1,127 @@ +/** +* 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 */ +describe('OC.Upload tests', function() { + var $dummyUploader; + var testFile; + + beforeEach(function() { + testFile = { + name: 'test.txt', + size: 5000, // 5 KB + type: 'text/plain', + lastModifiedDate: new Date() + }; + // need a dummy button because file-upload checks on it + $('#testArea').append( + '' + + '' + // 10 MB + '' // 50 MB + ); + $dummyUploader = $('#file_upload_start'); + }); + afterEach(function() { + delete window.file_upload_param; + $dummyUploader = undefined; + }); + describe('Adding files for upload', function() { + var params; + var failStub; + + beforeEach(function() { + params = OC.Upload.init(); + failStub = sinon.stub(); + $dummyUploader.on('fileuploadfail', failStub); + }); + afterEach(function() { + params = undefined; + failStub = undefined; + }); + + /** + * Add file for upload + * @param file file data + */ + function addFile(file) { + return params.add.call( + $dummyUploader[0], + {}, + { + originalFiles: {}, + files: [file] + }); + } + + it('adds file when size is below limits', function() { + var result = addFile(testFile); + expect(result).toEqual(true); + }); + it('adds file when free space is unknown', function() { + var result; + $('#free_space').val(-2); + + result = addFile(testFile); + + expect(result).toEqual(true); + expect(failStub.notCalled).toEqual(true); + }); + it('does not add file if it exceeds upload limit', function() { + var result; + $('#upload_limit').val(1000); + + result = addFile(testFile); + + expect(result).toEqual(false); + expect(failStub.calledOnce).toEqual(true); + expect(failStub.getCall(0).args[1].textStatus).toEqual('sizeexceedlimit'); + expect(failStub.getCall(0).args[1].errorThrown).toEqual( + 'Total file size 5 kB exceeds upload limit 1000 B' + ); + }); + it('does not add file if it exceeds free space', function() { + var result; + $('#free_space').val(1000); + + result = addFile(testFile); + + expect(result).toEqual(false); + expect(failStub.calledOnce).toEqual(true); + expect(failStub.getCall(0).args[1].textStatus).toEqual('notenoughspace'); + expect(failStub.getCall(0).args[1].errorThrown).toEqual( + 'Not enough free space, you are uploading 5 kB but only 1000 B is left' + ); + }); + it('does not add file if it has invalid characters', function() { + var result; + testFile.name = 'stars*stars.txt'; + + result = addFile(testFile); + + expect(result).toEqual(false); + expect(failStub.calledOnce).toEqual(true); + expect(failStub.getCall(0).args[1].textStatus).toEqual('invalidcharacters'); + expect(failStub.getCall(0).args[1].errorThrown.substr(0, 12)).toEqual( + 'Invalid name' + ); + }); + }); +}); diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index ef7ddcb874..f5eafba509 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'); @@ -29,47 +30,89 @@ describe('FileActions tests', function() { $body.append(''); // dummy files table $filesTable = $body.append('
'); + FileList.files = []; }); afterEach(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'}); + var fileData = { + id: 18, + type: 'file', + name: 'testName.txt', + mimetype: 'plain/text', + size: '1234', + etag: 'a01234c', + mtime: '123456' + }; - // 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); + // note: FileActions.display() is called implicitly + var $tr = FileList.add(fileData); - 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); + // 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 8f4cb86ab4..7a2b56d559 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -21,6 +21,36 @@ /* global OC, FileList */ describe('FileList tests', function() { + var testFiles, alertStub, notificationStub, + pushStateStub; + + /** + * Generate test file data + */ + function generateFiles(startIndex, endIndex) { + var files = []; + var name; + for (var i = startIndex; i <= endIndex; i++) { + name = 'File with index '; + if (i < 10) { + // do not rely on localeCompare here + // and make the sorting predictable + // cross-browser + name += '0'; + } + name += i + '.txt'; + files.push({ + id: i, + type: 'file', + name: name, + mimetype: 'text/plain', + size: i * 2, + etag: 'abc' + }); + } + return files; + } + beforeEach(function() { // init horrible parameters var $body = $('body'); @@ -28,45 +58,1378 @@ 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 + // TODO: at some point this will be rendered by the FileList class itself! + '' + + '' + + '' + + '' + + '
' + + '
Empty content message
' + ); + + testFiles = [{ + id: 1, + type: 'file', + name: 'One.txt', + mimetype: 'text/plain', + size: 12, + etag: 'abc' + }, { + id: 2, + type: 'file', + name: 'Two.jpg', + mimetype: 'image/jpeg', + size: 12049, + etag: 'def', + }, { + id: 3, + type: 'file', + name: 'Three.pdf', + mimetype: 'application/pdf', + size: 58009, + etag: '123', + }, { + id: 4, + type: 'dir', + name: 'somedir', + mimetype: 'httpd/unix-directory', + size: 250, + etag: '456' + }]; + + 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(); }); - 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('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); + }); }); - it('generates dir element with correct attributes when calling addDir', function() { - var lastMod = new Date(10000); - var $tr = FileList.addDir('testFolder', 1234, lastMod, false); + 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-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'); + 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', function() { + var $tr; + var fileData = { + type: 'file', + name: 'ZZZ.txt' + }; + FileList.setFiles(testFiles); + $tr = FileList.add(fileData); + expect($tr.index()).toEqual(4); + }); + it('inserts files in a sorted manner when insert option is enabled', function() { + var $tr; + for (var i = 0; i < testFiles.length; i++) { + FileList.add(testFiles[i]); + } + expect(FileList.files[0].name).toEqual('somedir'); + expect(FileList.files[1].name).toEqual('One.txt'); + expect(FileList.files[2].name).toEqual('Three.pdf'); + expect(FileList.files[3].name).toEqual('Two.jpg'); + }); + it('inserts new file at correct position', function() { + var $tr; + var fileData = { + type: 'file', + name: 'P comes after O.txt' + }; + for (var i = 0; i < testFiles.length; i++) { + FileList.add(testFiles[i]); + } + $tr = FileList.add(fileData); + // after "One.txt" + expect($tr.index()).toEqual(2); + expect(FileList.files[2]).toEqual(fileData); + }); + it('inserts new folder at correct position in insert mode', function() { + var $tr; + var fileData = { + type: 'dir', + name: 'somedir2 comes after somedir' + }; + for (var i = 0; i < testFiles.length; i++) { + FileList.add(testFiles[i]); + } + $tr = FileList.add(fileData); + expect($tr.index()).toEqual(1); + expect(FileList.files[1]).toEqual(fileData); + }); + it('inserts new file at the end correctly', function() { + var $tr; + var fileData = { + type: 'file', + name: 'zzz.txt' + }; + for (var i = 0; i < testFiles.length; i++) { + FileList.add(testFiles[i]); + } + $tr = FileList.add(fileData); + expect($tr.index()).toEqual(4); + expect(FileList.files[4]).toEqual(fileData); + }); + 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 = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(false); + // 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); + }); + }); + 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').length).toEqual(3); + expect(FileList.files.length).toEqual(3); + expect(FileList.findFileEl('One.txt').length).toEqual(0); + + $summary = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(false); + 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').length).toEqual(0); + expect(FileList.files.length).toEqual(0); + expect(FileList.findFileEl('One.txt').length).toEqual(0); + + $summary = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(true); + expect($('#filestable thead th').hasClass('hidden')).toEqual(true); + expect($('#emptycontent').hasClass('hidden')).toEqual(false); + expect(FileList.isEmpty).toEqual(true); + }); + }); + 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').length).toEqual(2); + + $summary = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(false); + 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('shows spinner on files to be deleted', function() { + FileList.setFiles(testFiles); + doDelete(); + + expect(FileList.findFileEl('One.txt').find('.progress-icon:not(.delete-icon)').length).toEqual(1); + expect(FileList.findFileEl('Three.pdf').find('.delete-icon:not(.progress-icon)').length).toEqual(1); + }); + it('shows spinner on all files when deleting all', function() { + FileList.setFiles(testFiles); + + FileList.do_delete(); + + expect(FileList.$fileList.find('tr .progress-icon:not(.delete-icon)').length).toEqual(4); + }); + 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').length).toEqual(0); + + $summary = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(true); + expect(FileList.isEmpty).toEqual(true); + expect(FileList.files.length).toEqual(0); + 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').length).toEqual(4); + + expect(notificationStub.calledOnce).toEqual(true); + }); + }); + describe('Renaming files', function() { + function doRename() { + var $input, request; + + for (var i = 0; i < testFiles.length; i++) { + FileList.add(testFiles[i]); + } + + // trigger rename prompt + FileList.rename('One.txt'); + $input = FileList.$fileList.find('input.filename'); + $input.val('Tu_after_three.txt').blur(); + + expect(fakeServer.requests.length).toEqual(1); + 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: 'Tu_after_three.txt', file: 'One.txt'}); + + // element is renamed before the request finishes + expect(FileList.findFileEl('One.txt').length).toEqual(0); + expect(FileList.findFileEl('Tu_after_three.txt').length).toEqual(1); + // input is gone + expect(FileList.$fileList.find('input.filename').length).toEqual(0); + } + it('Inserts renamed file entry at correct position if rename ajax call suceeded', function() { + doRename(); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'Tu_after_three.txt', + type: 'file' + } + })); + + // element stays renamed + expect(FileList.findFileEl('One.txt').length).toEqual(0); + expect(FileList.findFileEl('Tu_after_three.txt').length).toEqual(1); + expect(FileList.findFileEl('Tu_after_three.txt').index()).toEqual(2); // after Two.txt + + 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.txt').index()).toEqual(1); // after somedir + expect(FileList.findFileEl('Tu_after_three.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: 'Tu_after_three.txt' + } + })); + + $tr = FileList.findFileEl('Tu_after_three.txt'); + expect($tr.find('a.name').attr('href')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=Tu_after_three.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: 'Tu_after_three.txt' + } + })); + + $tr = FileList.findFileEl('Tu_after_three.txt'); + expect($tr.find('a.name').attr('href')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=One.txt'); + }); + }); + describe('Moving files', function() { + beforeEach(function() { + FileList.setFiles(testFiles); + }); + it('Moves single file to target folder', function() { + var request; + FileList.move('One.txt', '/somedir'); + + expect(fakeServer.requests.length).toEqual(1); + request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); + expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'One.txt', target: '/somedir'}); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'One.txt', + type: 'file' + } + })); + + expect(FileList.findFileEl('One.txt').length).toEqual(0); + + // folder size has increased + expect(FileList.findFileEl('somedir').data('size')).toEqual(262); + expect(FileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); + + expect(notificationStub.notCalled).toEqual(true); + }); + it('Moves list of files to target folder', function() { + var request; + FileList.move(['One.txt', 'Two.jpg'], '/somedir'); + + expect(fakeServer.requests.length).toEqual(2); + request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); + expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'One.txt', target: '/somedir'}); + + request = fakeServer.requests[1]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); + expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'Two.jpg', target: '/somedir'}); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'One.txt', + type: 'file' + } + })); + + expect(FileList.findFileEl('One.txt').length).toEqual(0); + + // folder size has increased + expect(FileList.findFileEl('somedir').data('size')).toEqual(262); + expect(FileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B'); + + fakeServer.requests[1].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'success', + data: { + name: 'Two.jpg', + type: 'file' + } + })); + + expect(FileList.findFileEl('Two.jpg').length).toEqual(0); + + // folder size has increased + expect(FileList.findFileEl('somedir').data('size')).toEqual(12311); + expect(FileList.findFileEl('somedir').find('.filesize').text()).toEqual('12 kB'); + + expect(notificationStub.notCalled).toEqual(true); + }); + it('Shows notification if a file could not be moved', function() { + var request; + FileList.move('One.txt', '/somedir'); + + expect(fakeServer.requests.length).toEqual(1); + request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/move.php'); + expect(OC.parseQueryString(request.requestBody)).toEqual({dir: '/subdir', file: 'One.txt', target: '/somedir'}); + + fakeServer.requests[0].respond(200, {'Content-Type': 'application/json'}, JSON.stringify({ + status: 'error', + data: { + message: 'Error while moving file', + } + })); + + expect(FileList.findFileEl('One.txt').length).toEqual(1); + + expect(notificationStub.calledOnce).toEqual(true); + expect(notificationStub.getCall(0).args[0]).toEqual('Error while moving file'); + }); + }); + describe('List rendering', function() { + it('renders a list of files using add()', function() { + expect(FileList.files.length).toEqual(0); + expect(FileList.files).toEqual([]); + FileList.setFiles(testFiles); + expect($('#fileList tr').length).toEqual(4); + expect(FileList.files.length).toEqual(4); + expect(FileList.files).toEqual(testFiles); + }); + it('updates summary using the file sizes', function() { + var $summary; + FileList.setFiles(testFiles); + $summary = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(false); + 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.$el.find('.summary').hasClass('hidden')).toEqual(false); + }); + 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.$el.find('.summary').hasClass('hidden')).toEqual(true); + }); + 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.$el.find('.summary').hasClass('hidden')).toEqual(true); + }); + 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); + }); + it('does not update summary when removing non-existing files', function() { + // single file + FileList.setFiles([testFiles[0]]); + $summary = $('#filestable .summary'); + expect($summary.hasClass('hidden')).toEqual(false); + expect($summary.find('.info').text()).toEqual('0 folders and 1 file'); + FileList.remove('unexist.txt'); + expect($summary.hasClass('hidden')).toEqual(false); + expect($summary.find('.info').text()).toEqual('0 folders and 1 file'); + }); + }); + describe('Rendering next page on scroll', function() { + beforeEach(function() { + FileList.setFiles(generateFiles(0, 64)); + }); + it('renders only the first page', function() { + expect(FileList.files.length).toEqual(65); + expect($('#fileList tr').length).toEqual(20); + }); + it('renders the second page when scrolling down (trigger nextPage)', function() { + // TODO: can't simulate scrolling here, so calling nextPage directly + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(40); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(60); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(65); + FileList._nextPage(true); + // stays at 65 + expect($('#fileList tr').length).toEqual(65); + }); + it('inserts into the DOM if insertion point is in the visible page ', function() { + FileList.add({ + id: 2000, + type: 'file', + name: 'File with index 15b.txt' + }); + expect($('#fileList tr').length).toEqual(21); + expect(FileList.findFileEl('File with index 15b.txt').index()).toEqual(16); + }); + it('does not inserts into the DOM if insertion point is not the visible page ', function() { + FileList.add({ + id: 2000, + type: 'file', + name: 'File with index 28b.txt' + }); + expect($('#fileList tr').length).toEqual(20); + expect(FileList.findFileEl('File with index 28b.txt').length).toEqual(0); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(40); + expect(FileList.findFileEl('File with index 28b.txt').index()).toEqual(29); + }); + it('appends into the DOM when inserting a file after the last visible element', function() { + FileList.add({ + id: 2000, + type: 'file', + name: 'File with index 19b.txt' + }); + expect($('#fileList tr').length).toEqual(21); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(41); + }); + it('appends into the DOM when inserting a file on the last page when visible', function() { + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(40); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(60); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(65); + FileList._nextPage(true); + FileList.add({ + id: 2000, + type: 'file', + name: 'File with index 88.txt' + }); + expect($('#fileList tr').length).toEqual(66); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(66); + }); + it('shows additional page when appending a page of files and scrolling down', function() { + var newFiles = generateFiles(66, 81); + for (var i = 0; i < newFiles.length; i++) { + FileList.add(newFiles[i]); + } + expect($('#fileList tr').length).toEqual(20); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(40); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(60); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(80); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(81); + FileList._nextPage(true); + expect($('#fileList tr').length).toEqual(81); + }); + it('automatically renders next page when there are not enough elements visible', function() { + // delete the 15 first elements + for (var i = 0; i < 15; i++) { + FileList.remove(FileList.files[0].name); + } + // still makes sure that there are 20 elements visible, if any + expect($('#fileList tr').length).toEqual(25); + }); + }); + 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').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 + ui.helper.find.returns([ + $(''), + $('') + ]); + // simulate drop event + FileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), 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 + ui.helper.find.returns([ + $(''), + $('') + ]); + // simulate drop event + FileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), 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'); + }); + }); + describe('File selection', function() { + beforeEach(function() { + FileList.setFiles(testFiles); + }); + it('Selects a file when clicking its checkbox', function() { + var $tr = FileList.findFileEl('One.txt'); + expect($tr.find('input:checkbox').prop('checked')).toEqual(false); + $tr.find('td.filename input:checkbox').click(); + + expect($tr.find('input:checkbox').prop('checked')).toEqual(true); + }); + it('Selects/deselect a file when clicking on the name while holding Ctrl', function() { + var $tr = FileList.findFileEl('One.txt'); + var $tr2 = FileList.findFileEl('Three.pdf'); + var e; + expect($tr.find('input:checkbox').prop('checked')).toEqual(false); + expect($tr2.find('input:checkbox').prop('checked')).toEqual(false); + e = new $.Event('click'); + e.ctrlKey = true; + $tr.find('td.filename .name').trigger(e); + + expect($tr.find('input:checkbox').prop('checked')).toEqual(true); + expect($tr2.find('input:checkbox').prop('checked')).toEqual(false); + + // click on second entry, does not clear the selection + e = new $.Event('click'); + e.ctrlKey = true; + $tr2.find('td.filename .name').trigger(e); + expect($tr.find('input:checkbox').prop('checked')).toEqual(true); + expect($tr2.find('input:checkbox').prop('checked')).toEqual(true); + + expect(_.pluck(FileList.getSelectedFiles(), 'name')).toEqual(['One.txt', 'Three.pdf']); + + // deselect now + e = new $.Event('click'); + e.ctrlKey = true; + $tr2.find('td.filename .name').trigger(e); + expect($tr.find('input:checkbox').prop('checked')).toEqual(true); + expect($tr2.find('input:checkbox').prop('checked')).toEqual(false); + expect(_.pluck(FileList.getSelectedFiles(), 'name')).toEqual(['One.txt']); + }); + it('Selects a range when clicking on one file then Shift clicking on another one', function() { + var $tr = FileList.findFileEl('One.txt'); + var $tr2 = FileList.findFileEl('Three.pdf'); + var e; + $tr.find('td.filename input:checkbox').click(); + e = new $.Event('click'); + e.shiftKey = true; + $tr2.find('td.filename .name').trigger(e); + + expect($tr.find('input:checkbox').prop('checked')).toEqual(true); + expect($tr2.find('input:checkbox').prop('checked')).toEqual(true); + expect(FileList.findFileEl('Two.jpg').find('input:checkbox').prop('checked')).toEqual(true); + var selection = _.pluck(FileList.getSelectedFiles(), 'name'); + expect(selection.length).toEqual(3); + expect(selection).toContain('One.txt'); + expect(selection).toContain('Two.jpg'); + expect(selection).toContain('Three.pdf'); + }); + it('Selects a range when clicking on one file then Shift clicking on another one that is above the first one', function() { + var $tr = FileList.findFileEl('One.txt'); + var $tr2 = FileList.findFileEl('Three.pdf'); + var e; + $tr2.find('td.filename input:checkbox').click(); + e = new $.Event('click'); + e.shiftKey = true; + $tr.find('td.filename .name').trigger(e); + + expect($tr.find('input:checkbox').prop('checked')).toEqual(true); + expect($tr2.find('input:checkbox').prop('checked')).toEqual(true); + expect(FileList.findFileEl('Two.jpg').find('input:checkbox').prop('checked')).toEqual(true); + var selection = _.pluck(FileList.getSelectedFiles(), 'name'); + expect(selection.length).toEqual(3); + expect(selection).toContain('One.txt'); + expect(selection).toContain('Two.jpg'); + expect(selection).toContain('Three.pdf'); + }); + it('Selecting all files will automatically check "select all" checkbox', function() { + expect($('#select_all').prop('checked')).toEqual(false); + $('#fileList tr td.filename input:checkbox').click(); + expect($('#select_all').prop('checked')).toEqual(true); + }); + it('Selecting all files on the first visible page will not automatically check "select all" checkbox', function() { + FileList.setFiles(generateFiles(0, 41)); + expect($('#select_all').prop('checked')).toEqual(false); + $('#fileList tr td.filename input:checkbox').click(); + expect($('#select_all').prop('checked')).toEqual(false); + }); + it('Clicking "select all" will select/deselect all files', function() { + FileList.setFiles(generateFiles(0, 41)); + $('#select_all').click(); + expect($('#select_all').prop('checked')).toEqual(true); + $('#fileList tr input:checkbox').each(function() { + expect($(this).prop('checked')).toEqual(true); + }); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(42); + + $('#select_all').click(); + expect($('#select_all').prop('checked')).toEqual(false); + + $('#fileList tr input:checkbox').each(function() { + expect($(this).prop('checked')).toEqual(false); + }); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(0); + }); + it('Clicking "select all" then deselecting a file will uncheck "select all"', function() { + $('#select_all').click(); + expect($('#select_all').prop('checked')).toEqual(true); + + var $tr = FileList.findFileEl('One.txt'); + $tr.find('input:checkbox').click(); + + expect($('#select_all').prop('checked')).toEqual(false); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(3); + }); + it('Updates the selection summary when doing a few manipulations with "Select all"', function() { + $('#select_all').click(); + expect($('#select_all').prop('checked')).toEqual(true); + + var $tr = FileList.findFileEl('One.txt'); + // unselect one + $tr.find('input:checkbox').click(); + + expect($('#select_all').prop('checked')).toEqual(false); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(3); + + // select all + $('#select_all').click(); + expect($('#select_all').prop('checked')).toEqual(true); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(4); + + // unselect one + $tr.find('input:checkbox').click(); + expect($('#select_all').prop('checked')).toEqual(false); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(3); + + // re-select it + $tr.find('input:checkbox').click(); + expect($('#select_all').prop('checked')).toEqual(true); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(4); + }); + it('Auto-selects files on next page when "select all" is checked', function() { + FileList.setFiles(generateFiles(0, 41)); + $('#select_all').click(); + + expect(FileList.$fileList.find('tr input:checkbox:checked').length).toEqual(20); + FileList._nextPage(true); + expect(FileList.$fileList.find('tr input:checkbox:checked').length).toEqual(40); + FileList._nextPage(true); + expect(FileList.$fileList.find('tr input:checkbox:checked').length).toEqual(42); + expect(_.pluck(FileList.getSelectedFiles(), 'name').length).toEqual(42); + }); + it('Selecting files updates selection summary', function() { + var $summary = $('#headerName span.name'); + expect($summary.text()).toEqual('Name'); + FileList.findFileEl('One.txt').find('input:checkbox').click(); + FileList.findFileEl('Three.pdf').find('input:checkbox').click(); + FileList.findFileEl('somedir').find('input:checkbox').click(); + expect($summary.text()).toEqual('1 folder & 2 files'); + }); + it('Unselecting files hides selection summary', function() { + var $summary = $('#headerName span.name'); + FileList.findFileEl('One.txt').find('input:checkbox').click().click(); + expect($summary.text()).toEqual('Name'); + }); + it('Select/deselect files shows/hides file actions', function() { + var $actions = $('#headerName .selectedActions'); + var $checkbox = FileList.findFileEl('One.txt').find('input:checkbox'); + expect($actions.hasClass('hidden')).toEqual(true); + $checkbox.click(); + expect($actions.hasClass('hidden')).toEqual(false); + $checkbox.click(); + expect($actions.hasClass('hidden')).toEqual(true); + }); + it('Selection is cleared when switching dirs', function() { + $('#select_all').click(); + var data = { + status: 'success', + data: { + files: testFiles, + permissions: 31 + } + }; + fakeServer.respondWith(/\/index\.php\/apps\/files\/ajax\/list.php/, [ + 200, { + "Content-Type": "application/json" + }, + JSON.stringify(data) + ]); + FileList.changeDirectory('/'); + fakeServer.respond(); + expect($('#select_all').prop('checked')).toEqual(false); + expect(_.pluck(FileList.getSelectedFiles(), 'name')).toEqual([]); + }); + it('getSelectedFiles returns the selected files even when they are on the next page', function() { + var selectedFiles; + FileList.setFiles(generateFiles(0, 41)); + $('#select_all').click(); + // unselect one to not have the "allFiles" case + FileList.$fileList.find('tr input:checkbox:first').click(); + + // only 20 files visible, must still return all the selected ones + selectedFiles = _.pluck(FileList.getSelectedFiles(), 'name'); + + expect(selectedFiles.length).toEqual(41); + }); + describe('Actions', function() { + beforeEach(function() { + FileList.findFileEl('One.txt').find('input:checkbox').click(); + FileList.findFileEl('Three.pdf').find('input:checkbox').click(); + FileList.findFileEl('somedir').find('input:checkbox').click(); + }); + it('getSelectedFiles returns the selected file data', function() { + var files = FileList.getSelectedFiles(); + expect(files.length).toEqual(3); + expect(files[0]).toEqual({ + id: 1, + name: 'One.txt', + mimetype: 'text/plain', + type: 'file', + size: 12, + etag: 'abc' + }); + expect(files[1]).toEqual({ + id: 3, + type: 'file', + name: 'Three.pdf', + mimetype: 'application/pdf', + size: 58009, + etag: '123' + }); + expect(files[2]).toEqual({ + id: 4, + type: 'dir', + name: 'somedir', + mimetype: 'httpd/unix-directory', + size: 250, + etag: '456' + }); + }); + it('Removing a file removes it from the selection', function() { + FileList.remove('Three.pdf'); + var files = FileList.getSelectedFiles(); + expect(files.length).toEqual(2); + expect(files[0]).toEqual({ + id: 1, + name: 'One.txt', + mimetype: 'text/plain', + type: 'file', + size: 12, + etag: 'abc' + }); + expect(files[1]).toEqual({ + id: 4, + type: 'dir', + name: 'somedir', + mimetype: 'httpd/unix-directory', + size: 250, + etag: '456' + }); + }); + describe('Download', function() { + it('Opens download URL when clicking "Download"', function() { + var redirectStub = sinon.stub(OC, 'redirect'); + $('.selectedActions .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=%5B%22One.txt%22%2C%22Three.pdf%22%2C%22somedir%22%5D'); + redirectStub.restore(); + }); + it('Downloads root folder when all selected in root folder', function() { + $('#dir').val('/'); + $('#select_all').click(); + var redirectStub = sinon.stub(OC, 'redirect'); + $('.selectedActions .download').click(); + expect(redirectStub.calledOnce).toEqual(true); + expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files='); + redirectStub.restore(); + }); + it('Downloads parent folder when all selected in subfolder', function() { + $('#select_all').click(); + var redirectStub = sinon.stub(OC, 'redirect'); + $('.selectedActions .download').click(); + expect(redirectStub.calledOnce).toEqual(true); + expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=subdir'); + redirectStub.restore(); + }); + }); + describe('Delete', function() { + it('Deletes selected files when "Delete" clicked', function() { + var request; + $('.selectedActions .delete-selected').click(); + expect(fakeServer.requests.length).toEqual(1); + request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php'); + expect(OC.parseQueryString(request.requestBody)) + .toEqual({'dir': '/subdir', files: '["One.txt","Three.pdf","somedir"]'}); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(FileList.findFileEl('One.txt').length).toEqual(0); + expect(FileList.findFileEl('Three.pdf').length).toEqual(0); + expect(FileList.findFileEl('somedir').length).toEqual(0); + expect(FileList.findFileEl('Two.jpg').length).toEqual(1); + }); + it('Deletes all files when all selected when "Delete" clicked', function() { + var request; + $('#select_all').click(); + $('.selectedActions .delete-selected').click(); + expect(fakeServer.requests.length).toEqual(1); + request = fakeServer.requests[0]; + expect(request.url).toEqual(OC.webroot + '/index.php/apps/files/ajax/delete.php'); + expect(OC.parseQueryString(request.requestBody)) + .toEqual({'dir': '/subdir', allfiles: 'true'}); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({status: 'success'}) + ); + expect(FileList.isEmpty).toEqual(true); + }); + }); }); }); }); diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index 018c8ef0f3..7f8848619f 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -19,7 +19,7 @@ * */ -/* global Files */ +/* global OC, Files */ describe('Files tests', function() { describe('File name validation', function() { it('Validates correct file names', function() { @@ -82,4 +82,30 @@ describe('Files tests', function() { } }); }); + describe('getDownloadUrl', function() { + var curDirStub; + beforeEach(function() { + curDirStub = sinon.stub(FileList, 'getCurrentDirectory'); + }); + afterEach(function() { + curDirStub.restore(); + }); + it('returns the ajax download URL when only filename specified', function() { + curDirStub.returns('/subdir'); + var url = Files.getDownloadUrl('test file.txt'); + expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20file.txt'); + }); + it('returns the ajax download URL when filename and dir specified', function() { + var url = Files.getDownloadUrl('test file.txt', '/subdir'); + expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=test%20file.txt'); + }); + it('returns the ajax download URL when filename and root dir specific', function() { + var url = Files.getDownloadUrl('test file.txt', '/'); + expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=test%20file.txt'); + }); + it('returns the ajax download URL when multiple files specified', function() { + var url = Files.getDownloadUrl(['test file.txt', 'abc.txt'], '/subdir'); + expect(url).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=%5B%22test%20file.txt%22%2C%22abc.txt%22%5D'); + }); + }); }); diff --git a/apps/files/tests/js/filesummarySpec.js b/apps/files/tests/js/filesummarySpec.js new file mode 100644 index 0000000000..c493700de3 --- /dev/null +++ b/apps/files/tests/js/filesummarySpec.js @@ -0,0 +1,87 @@ +/** +* 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 FileSummary */ +describe('FileSummary tests', function() { + var $container; + + beforeEach(function() { + $container = $('
').find('tr'); + }); + afterEach(function() { + $container = null; + }); + + it('renders summary as text', function() { + var s = new FileSummary($container); + s.setSummary({ + totalDirs: 5, + totalFiles: 2, + totalSize: 256000 + }); + expect($container.hasClass('hidden')).toEqual(false); + expect($container.find('.info').text()).toEqual('5 folders and 2 files'); + expect($container.find('.filesize').text()).toEqual('250 kB'); + }); + it('hides summary when no files or folders', function() { + var s = new FileSummary($container); + s.setSummary({ + totalDirs: 0, + totalFiles: 0, + totalSize: 0 + }); + expect($container.hasClass('hidden')).toEqual(true); + }); + it('increases summary when adding files', function() { + var s = new FileSummary($container); + s.setSummary({ + totalDirs: 5, + totalFiles: 2, + totalSize: 256000 + }); + s.add({type: 'file', size: 256000}); + s.add({type: 'dir', size: 100}); + s.update(); + expect($container.hasClass('hidden')).toEqual(false); + expect($container.find('.info').text()).toEqual('6 folders and 3 files'); + expect($container.find('.filesize').text()).toEqual('500 kB'); + expect(s.summary.totalDirs).toEqual(6); + expect(s.summary.totalFiles).toEqual(3); + expect(s.summary.totalSize).toEqual(512100); + }); + it('decreases summary when removing files', function() { + var s = new FileSummary($container); + s.setSummary({ + totalDirs: 5, + totalFiles: 2, + totalSize: 256000 + }); + s.remove({type: 'file', size: 128000}); + s.remove({type: 'dir', size: 100}); + s.update(); + expect($container.hasClass('hidden')).toEqual(false); + expect($container.find('.info').text()).toEqual('4 folders and 1 file'); + expect($container.find('.filesize').text()).toEqual('125 kB'); + expect(s.summary.totalDirs).toEqual(4); + expect(s.summary.totalFiles).toEqual(1); + expect(s.summary.totalSize).toEqual(127900); + }); +}); diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml index b6d9d6bb0a..15a09a29f5 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. + 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/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 3af43f1026..5f0494e62c 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -302,25 +302,6 @@ class Hooks { */ public static function postShared($params) { - // NOTE: $params has keys: - // [itemType] => file - // itemSource -> int, filecache file ID - // [parent] => - // [itemTarget] => /13 - // shareWith -> string, uid of user being shared to - // fileTarget -> path of file being shared - // uidOwner -> owner of the original file being shared - // [shareType] => 0 - // [shareWith] => test1 - // [uidOwner] => admin - // [permissions] => 17 - // [fileSource] => 13 - // [fileTarget] => /test8 - // [id] => 10 - // [token] => - // [run] => whether emitting script should continue to run - // TODO: Should other kinds of item be encrypted too? - if (\OCP\App::isEnabled('files_encryption') === false) { return true; } @@ -331,71 +312,22 @@ class Hooks { $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); - $path = $util->fileIdToPath($params['itemSource']); - - $share = $util->getParentFromShare($params['id']); - //if parent is set, then this is a re-share action - if ($share['parent'] !== null) { - - // get the parent from current share - $parent = $util->getShareParent($params['parent']); - - // if parent has the same type than the child it is a 1:1 share - if ($parent['item_type'] === $params['itemType']) { - - // prefix path with Shared - $path = '/Shared' . $parent['file_target']; - } else { - - // NOTE: parent is folder but shared was a file! - // we try to rebuild the missing path - // some examples we face here - // user1 share folder1 with user2 folder1 has - // the following structure - // /folder1/subfolder1/subsubfolder1/somefile.txt - // user2 re-share subfolder2 with user3 - // user3 re-share somefile.txt user4 - // so our path should be - // /Shared/subfolder1/subsubfolder1/somefile.txt - // while user3 is sharing - - if ($params['itemType'] === 'file') { - // get target path - $targetPath = $util->fileIdToPath($params['fileSource']); - $targetPathSplit = array_reverse(explode('/', $targetPath)); - - // init values - $path = ''; - $sharedPart = ltrim($parent['file_target'], '/'); - - // rebuild path - foreach ($targetPathSplit as $pathPart) { - if ($pathPart !== $sharedPart) { - $path = '/' . $pathPart . $path; - } else { - break; - } - } - // prefix path with Shared - $path = '/Shared' . $parent['file_target'] . $path; - } else { - // prefix path with Shared - $path = '/Shared' . $parent['file_target'] . $params['fileTarget']; - } - } - } + $path = \OC\Files\Filesystem::getPath($params['fileSource']); $sharingEnabled = \OCP\Share::isEnabled(); // get the path including mount point only if not a shared folder - if (strncmp($path, '/Shared', strlen('/Shared') !== 0)) { - // get path including the the storage mount point - $path = $util->getPathWithMountPoint($params['itemSource']); + list($storage, ) = \OC\Files\Filesystem::resolvePath('/' . $userId . '/files' . $path); + + if (!($storage instanceof \OC\Files\Storage\Local)) { + $mountPoint = 'files' . $storage->getMountPoint(); + } else { + $mountPoint = ''; } // if a folder was shared, get a list of all (sub-)folders if ($params['itemType'] === 'folder') { - $allFiles = $util->getAllFiles($path); + $allFiles = $util->getAllFiles($path, $mountPoint); } else { $allFiles = array($path); } @@ -412,13 +344,6 @@ class Hooks { */ public static function postUnshare($params) { - // NOTE: $params has keys: - // [itemType] => file - // [itemSource] => 13 - // [shareType] => 0 - // [shareWith] => test1 - // [itemParent] => - if (\OCP\App::isEnabled('files_encryption') === false) { return true; } @@ -428,34 +353,7 @@ class Hooks { $view = new \OC_FilesystemView('/'); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); - $path = $util->fileIdToPath($params['itemSource']); - - // check if this is a re-share - if ($params['itemParent']) { - - // get the parent from current share - $parent = $util->getShareParent($params['itemParent']); - - // get target path - $targetPath = $util->fileIdToPath($params['itemSource']); - $targetPathSplit = array_reverse(explode('/', $targetPath)); - - // init values - $path = ''; - $sharedPart = ltrim($parent['file_target'], '/'); - - // rebuild path - foreach ($targetPathSplit as $pathPart) { - if ($pathPart !== $sharedPart) { - $path = '/' . $pathPart . $path; - } else { - break; - } - } - - // prefix path with Shared - $path = '/Shared' . $parent['file_target'] . $path; - } + $path = \OC\Files\Filesystem::getPath($params['fileSource']); // for group shares get a list of the group members if ($params['shareType'] === \OCP\Share::SHARE_TYPE_GROUP) { @@ -469,14 +367,17 @@ class Hooks { } // get the path including mount point only if not a shared folder - if (strncmp($path, '/Shared', strlen('/Shared') !== 0)) { - // get path including the the storage mount point - $path = $util->getPathWithMountPoint($params['itemSource']); + list($storage, ) = \OC\Files\Filesystem::resolvePath('/' . $userId . '/files' . $path); + + if (!($storage instanceof \OC\Files\Storage\Local)) { + $mountPoint = 'files' . $storage->getMountPoint(); + } else { + $mountPoint = ''; } // if we unshare a folder we need a list of all (sub-)files if ($params['itemType'] === 'folder') { - $allFiles = $util->getAllFiles($path); + $allFiles = $util->getAllFiles($path, $mountPoint); } else { $allFiles = array($path); } @@ -501,11 +402,22 @@ class Hooks { * @param array $params with the old path and the new path */ public static function preRename($params) { - $util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); + $user = \OCP\User::getUser(); + $view = new \OC_FilesystemView('/'); + $util = new Util($view, $user); list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']); - self::$renamedFiles[$params['oldpath']] = array( - 'uid' => $ownerOld, - 'path' => $pathOld); + + // we only need to rename the keys if the rename happens on the same mountpoint + // otherwise we perform a stream copy, so we get a new set of keys + $mp1 = $view->getMountPoint('/' . $user . '/files/' . $params['oldpath']); + $mp2 = $view->getMountPoint('/' . $user . '/files/' . $params['newpath']); + list($storage1, ) = Filesystem::resolvePath($params['oldpath']); + + if ($mp1 === $mp2) { + self::$renamedFiles[$params['oldpath']] = array( + 'uid' => $ownerOld, + 'path' => $pathOld); + } } /** diff --git a/apps/files_encryption/js/settings-admin.js b/apps/files_encryption/js/settings-admin.js index c2140a6f1e..785d02002f 100644 --- a/apps/files_encryption/js/settings-admin.js +++ b/apps/files_encryption/js/settings-admin.js @@ -7,28 +7,6 @@ * See the COPYING-README file. */ -OC.msg={ - startSaving:function(selector){ - $(selector) - .html( t('settings', 'Saving...') ) - .removeClass('success') - .removeClass('error') - .stop(true, true) - .show(); - }, - finishedSaving:function(selector, data){ - if( data.status === "success" ){ - $(selector).html( data.data.message ) - .addClass('success') - .stop(true, true) - .delay(3000) - .fadeOut(900); - }else{ - $(selector).html( data.data.message ).addClass('error'); - } - } -}; - $(document).ready(function(){ // Trigger ajax on recoveryAdmin status change var enabledStatus = $('#adminEnableRecovery').val(); diff --git a/apps/files_encryption/l10n/ar.php b/apps/files_encryption/l10n/ar.php index 45a0c4616f..345c01a0d4 100644 --- a/apps/files_encryption/l10n/ar.php +++ b/apps/files_encryption/l10n/ar.php @@ -1,6 +1,44 @@ "جاري الحفظ...", -"Encryption" => "التشفير" +"Recovery key successfully enabled" => "تم بنجاح تفعيل مفتاح الاستعادة", +"Could not enable recovery key. Please check your recovery key password!" => "لا يمكن تفعيل مفتاح الاستعادة, يرجى التحقق من كلمة مرور مفتاح الاستعادة!", +"Recovery key successfully disabled" => "تم تعطيل مفتاح الاستعادة بنجاح", +"Could not disable recovery key. Please check your recovery key password!" => "لا يمكن تعطيل مفتاح الاستعادة, يرجى التحقق من كلمة مرور مفتاح الاستعادة!", +"Password successfully changed." => "تم تغيير كلمة المرور بنجاح.", +"Could not change the password. Maybe the old password was not correct." => "تعذر تغيير كلمة المرور. من الممكن ان كلمة المرور القديمة غير صحيحة.", +"Private key password successfully updated." => "تم تحديث كلمة المرور للمفتاح الخاص بنجاح.", +"Could not update the private key password. Maybe the old password was not correct." => "لا يمكن تحديث كلمة مرور المفتاح الخاص. من الممكن ان كلمة المرور القديمة غير صحيحة.", +"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "برنامج التشفير لم يتم تهيئتة ! من الممكن ان برنامج التشفير تم اعادة تفعيلة خلال الجلسة. يرجى تسجيل الخروج ومن ثم تسجيل الدخول مجددا لتهيئة برنامج التشفير.", +"Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "مفتاحك الخاص غير صالح! ربما تم تغيير كلمة المرور خارج %s (مثل:مجلد شركتك). يمكنك تحديث كلمة المرور في الاعدادات الشخصية لإستعادة الوصول الى ملفاتك المشفرة.", +"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "لا يمكن فك التشفير من هذا الملف, من الممكن ان يكون هذا الملف مُشارك. يرجى سؤال صاحب الملف لإعادة مشاركتة معك.", +"Unknown error please check your system settings or contact your administrator" => "خطا غير معروف يرجى التاكد من اعدادات نظامك او تواصل مع المدير.", +"Missing requirements." => "متطلبات ناقصة.", +"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 مفعل و مهيئ بشكل صحيح. حتى الان برنامج التتشفير تم تعطيلة.", +"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" => "التشفير", +"Enable recovery key (allow to recover users files in case of password loss):" => "تفعيل استعادة المفتاح (سوف يمكنك من استعادة ملفات المستخدمين في حال فقدان كلمة المرور):", +"Recovery key password" => "استعادة كلمة مرور المفتاح", +"Repeat Recovery key password" => "كرر كلمة المرور لـ استعادة المفتاح", +"Enabled" => "مفعلة", +"Disabled" => "معطلة", +"Change recovery key password:" => "تعديل كلمة المرور استعادة المفتاح:", +"Old Recovery key password" => "كلمة المرور القديمة لـ استعامة المفتاح", +"New Recovery key password" => "تعيين كلمة مرور جديدة لـ استعادة المفتاح", +"Repeat New Recovery key password" => "كرر كلمة المرور لـ استعادة المفتاح من جديد", +"Change Password" => "عدل كلمة السر", +"Your private key password no longer match your log-in password:" => "كلمة مرور مفتاحك الخاص لا تتطابق مع كلمة المرور الخاصة الدخول:", +"Set your old private key password to your current log-in password." => "تعيين كلمة المرور القديمة لـ المفتاح الخاص الى كلمة المرور الخاصة بالدخول الحالية.", +" If you don't remember your old password you can ask your administrator to recover your files." => "اذا كنت لاتتذكر كلمة السر تستطيع ان تطلب من المدير ان يستعيد ملفاتك.", +"Old log-in password" => "كلمة المرور القديمة الخاصة بالدخول", +"Current log-in password" => "كلمة المرور الحالية الخاصة بالدخول", +"Update Private Key Password" => "تحديث كلمة المرور لـ المفتاح الخاص", +"Enable password recovery:" => "تفعيل استعادة كلمة المرور:", +"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "تفعيل هذا الخيار يمكنك من اعادة الوصول الى ملفاتك المشفرة عند فقدان كلمة المرور", +"File recovery settings updated" => "اعدادات ملف الاستعادة تم تحديثه", +"Could not update file recovery" => "تعذر تحديث ملف الاستعادة" ); $PLURAL_FORMS = "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"; diff --git a/apps/files_encryption/l10n/ast.php b/apps/files_encryption/l10n/ast.php new file mode 100644 index 0000000000..7e08e07309 --- /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/bg_BG.php b/apps/files_encryption/l10n/bg_BG.php index 9060c92ed4..a40781125d 100644 --- a/apps/files_encryption/l10n/bg_BG.php +++ b/apps/files_encryption/l10n/bg_BG.php @@ -1,6 +1,5 @@ "Записване...", "Encryption" => "Криптиране" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/bn_BD.php b/apps/files_encryption/l10n/bn_BD.php index 5fc4f6a13f..63e335bd2b 100644 --- a/apps/files_encryption/l10n/bn_BD.php +++ b/apps/files_encryption/l10n/bn_BD.php @@ -1,6 +1,5 @@ "সংরক্ষণ করা হচ্ছে..", "Encryption" => "সংকেতায়ন" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/ca.php b/apps/files_encryption/l10n/ca.php index 33d2754483..3414796f62 100644 --- a/apps/files_encryption/l10n/ca.php +++ b/apps/files_encryption/l10n/ca.php @@ -16,7 +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." => "Assegureu-vos que teniu instal·lat PHP 5.3.3 o una versió superior i que està activat Open SSL i habilitada i configurada correctament l'extensió de PHP. De moment, l'aplicació d'encriptació s'ha desactivat.", "Following users are not set up for encryption:" => "Els usuaris següents no estan configurats per a l'encriptació:", "Initial encryption started... This can take some time. Please wait." => "La encriptació inicial ha començat... Pot trigar una estona, espereu.", -"Saving..." => "Desant...", +"Initial encryption running... Please try again later." => "encriptació inicial en procés... Proveu-ho més tard.", "Go directly to your " => "Vés directament a", "personal settings" => "arranjament personal", "Encryption" => "Xifrat", diff --git a/apps/files_encryption/l10n/cs_CZ.php b/apps/files_encryption/l10n/cs_CZ.php index cf2776371d..cdeaf5b192 100644 --- a/apps/files_encryption/l10n/cs_CZ.php +++ b/apps/files_encryption/l10n/cs_CZ.php @@ -16,7 +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." => "Ujistěte se prosím, že máte nainstalované PHP 5.3.3 nebo novější a že máte povolené a správně nakonfigurované OpenSSL včetně jeho rozšíření pro PHP. Prozatím byla aplikace pro šifrování vypnuta.", "Following users are not set up for encryption:" => "Následující uživatelé nemají nastavené šifrování:", "Initial encryption started... This can take some time. Please wait." => "Počáteční šifrování zahájeno... Toto může chvíli trvat. Počkejte prosím.", -"Saving..." => "Ukládám...", +"Initial encryption running... Please try again later." => "Probíhá počáteční šifrování... Zkuste to prosím znovu později.", "Go directly to your " => "Běžte přímo do vašeho", "personal settings" => "osobní nastavení", "Encryption" => "Šifrování", diff --git a/apps/files_encryption/l10n/cy_GB.php b/apps/files_encryption/l10n/cy_GB.php index ea8b19963b..6d3b898d00 100644 --- a/apps/files_encryption/l10n/cy_GB.php +++ b/apps/files_encryption/l10n/cy_GB.php @@ -1,6 +1,5 @@ "Yn cadw...", "Encryption" => "Amgryptiad" ); $PLURAL_FORMS = "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"; diff --git a/apps/files_encryption/l10n/da.php b/apps/files_encryption/l10n/da.php index 9e4290534c..f0f1580049 100644 --- a/apps/files_encryption/l10n/da.php +++ b/apps/files_encryption/l10n/da.php @@ -16,7 +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." => "Sørg for at PHP 5.3.3 eller nyere er installeret og at OpenSSL sammen med PHP-udvidelsen er aktiveret og korrekt konfigureret. Indtil videre er krypteringsprogrammet deaktiveret.", "Following users are not set up for encryption:" => "Følgende brugere er ikke sat op til kryptering:", "Initial encryption started... This can take some time. Please wait." => "Førstegangskryptering er påbegyndt... Dette kan tage nogen tid. Vent venligst.", -"Saving..." => "Gemmer...", +"Initial encryption running... Please try again later." => "Kryptering foretages... Prøv venligst igen senere.", "Go directly to your " => "Gå direkte til din ", "personal settings" => "Personlige indstillinger", "Encryption" => "Kryptering", diff --git a/apps/files_encryption/l10n/de.php b/apps/files_encryption/l10n/de.php index 3ba50f074b..38bfa7f024 100644 --- a/apps/files_encryption/l10n/de.php +++ b/apps/files_encryption/l10n/de.php @@ -16,7 +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." => "Bitte stelle sicher, dass PHP 5.3.3 oder neuer installiert und das OpenSSL zusammen mit der PHP-Erweiterung aktiviert und richtig konfiguriert ist. Zur Zeit ist die Verschlüsselungs-App deaktiviert.", "Following users are not set up for encryption:" => "Für folgende Nutzer ist keine Verschlüsselung eingerichtet:", "Initial encryption started... This can take some time. Please wait." => "Initialverschlüsselung gestartet... Dies kann einige Zeit dauern. Bitte warten.", -"Saving..." => "Speichern...", +"Initial encryption running... Please try again later." => "Initiale Verschlüsselung läuft... Bitte versuche es später wieder.", "Go directly to your " => "Direkt wechseln zu Deinem", "personal settings" => "Private Einstellungen", "Encryption" => "Verschlüsselung", diff --git a/apps/files_encryption/l10n/de_CH.php b/apps/files_encryption/l10n/de_CH.php index a31e82a666..875efa84f2 100644 --- a/apps/files_encryption/l10n/de_CH.php +++ b/apps/files_encryption/l10n/de_CH.php @@ -11,7 +11,6 @@ $TRANSLATIONS = array( "Missing requirements." => "Fehlende Voraussetzungen", "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." => "Bitte stellen Sie sicher, dass PHP 5.3.3 oder neuer installiert und das OpenSSL zusammen mit der PHP-Erweiterung aktiviert und richtig konfiguriert ist. Zur Zeit ist die Verschlüsselungs-App deaktiviert.", "Following users are not set up for encryption:" => "Für folgende Nutzer ist keine Verschlüsselung eingerichtet:", -"Saving..." => "Speichern...", "personal settings" => "Persönliche Einstellungen", "Encryption" => "Verschlüsselung", "Enable recovery key (allow to recover users files in case of password loss):" => "Aktivieren Sie den Wiederherstellungsschlüssel (erlaubt die Wiederherstellung des Zugangs zu den Benutzerdateien, wenn das Passwort verloren geht).", diff --git a/apps/files_encryption/l10n/de_DE.php b/apps/files_encryption/l10n/de_DE.php index 6184fd8a89..13f7718b93 100644 --- a/apps/files_encryption/l10n/de_DE.php +++ b/apps/files_encryption/l10n/de_DE.php @@ -15,8 +15,8 @@ $TRANSLATIONS = array( "Missing requirements." => "Fehlende Voraussetzungen", "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." => "Bitte stellen Sie sicher, dass PHP 5.3.3 oder neuer installiert und das OpenSSL zusammen mit der PHP-Erweiterung aktiviert und richtig konfiguriert ist. Zur Zeit ist die Verschlüsselungs-App deaktiviert.", "Following users are not set up for encryption:" => "Für folgende Nutzer ist keine Verschlüsselung eingerichtet:", -"Initial encryption started... This can take some time. Please wait." => "Initialverschlüsselung gestartet... Dies kann einige Zeit dauern. Bitte warten.", -"Saving..." => "Speichern...", +"Initial encryption started... This can take some time. Please wait." => "Anfangsverschlüsselung gestartet... Dies kann einige Zeit dauern. Bitte warten.", +"Initial encryption running... Please try again later." => "Anfangsverschlüsselung läuft... Bitte versuchen Sie es später wieder.", "Go directly to your " => "Direkt wechseln zu Ihrem", "personal settings" => "Persönliche Einstellungen", "Encryption" => "Verschlüsselung", diff --git a/apps/files_encryption/l10n/el.php b/apps/files_encryption/l10n/el.php index 22c1095e28..972d7d7138 100644 --- a/apps/files_encryption/l10n/el.php +++ b/apps/files_encryption/l10n/el.php @@ -16,7 +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." => "Η αρχική κρυπτογράφηση άρχισε... Αυτό μπορεί να πάρει κάποια ώρα. Παρακαλώ περιμένετε.", -"Saving..." => "Γίνεται αποθήκευση...", +"Initial encryption running... Please try again later." => "Εκτέλεση αρχικής κρυπτογράφησης... Παρακαλώ προσπαθήστε αργότερα.", "Go directly to your " => "Πηγαίνε απευθείας στο ", "personal settings" => "προσωπικές ρυθμίσεις", "Encryption" => "Κρυπτογράφηση", diff --git a/apps/files_encryption/l10n/en_GB.php b/apps/files_encryption/l10n/en_GB.php index 55d56b9533..2087ea4b8b 100644 --- a/apps/files_encryption/l10n/en_GB.php +++ b/apps/files_encryption/l10n/en_GB.php @@ -16,7 +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." => "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.", "Following users are not set up for encryption:" => "Following users are not set up for encryption:", "Initial encryption started... This can take some time. Please wait." => "Initial encryption started... This can take some time. Please wait.", -"Saving..." => "Saving...", +"Initial encryption running... Please try again later." => "Initial encryption running... Please try again later.", "Go directly to your " => "Go directly to your ", "personal settings" => "personal settings", "Encryption" => "Encryption", diff --git a/apps/files_encryption/l10n/eo.php b/apps/files_encryption/l10n/eo.php index e14c7cd7ac..05d30f2f6c 100644 --- a/apps/files_encryption/l10n/eo.php +++ b/apps/files_encryption/l10n/eo.php @@ -4,7 +4,6 @@ $TRANSLATIONS = array( "Could not change the password. Maybe the old password was not correct." => "Ne eblis ŝanĝi la pasvorton. Eble la malnova pasvorto malĝustis.", "Private key password successfully updated." => "La pasvorto de la malpublika klavo sukcese ĝisdatiĝis.", "Missing requirements." => "Mankas neproj.", -"Saving..." => "Konservante...", "Go directly to your " => "Iri direkte al via", "personal settings" => "persona agordo", "Encryption" => "Ĉifrado", diff --git a/apps/files_encryption/l10n/es.php b/apps/files_encryption/l10n/es.php index 5345398688..cf45437c0e 100644 --- a/apps/files_encryption/l10n/es.php +++ b/apps/files_encryption/l10n/es.php @@ -16,7 +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." => "Por favor, asegúrese de que PHP 5.3.3 o posterior está instalado y que la extensión OpenSSL de PHP está habilitada y configurada correctamente. Por el momento, la aplicación de cifrado ha sido deshabilitada.", "Following users are not set up for encryption:" => "Los siguientes usuarios no han sido configurados para el cifrado:", "Initial encryption started... This can take some time. Please wait." => "Encriptación iniciada..... Esto puede tomar un tiempo. Por favor espere.", -"Saving..." => "Guardando...", +"Initial encryption running... Please try again later." => "Cifrado inicial en curso... Inténtelo más tarde.", "Go directly to your " => "Ir directamente a su", "personal settings" => "opciones personales", "Encryption" => "Cifrado", diff --git a/apps/files_encryption/l10n/es_AR.php b/apps/files_encryption/l10n/es_AR.php index df5bd649d6..b885716f89 100644 --- a/apps/files_encryption/l10n/es_AR.php +++ b/apps/files_encryption/l10n/es_AR.php @@ -8,19 +8,27 @@ $TRANSLATIONS = array( "Could not change the password. Maybe the old password was not correct." => "No se pudo cambiar la contraseña. Comprobá que la contraseña actual sea correcta.", "Private key password successfully updated." => "Contraseña de clave privada actualizada con éxito.", "Could not update the private key password. Maybe the old password was not correct." => "No fue posible actualizar la contraseña de clave privada. Tal vez la contraseña anterior no es correcta.", +"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "¡La aplicación de encriptación no está inicializada! Es probable que la aplicación fue re-habilitada durante tu sesión. Intenta salir y iniciar sesión para volverla a iniciar.", +"Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "¡Tu llave privada no es válida! Aparenta que tu clave fue cambiada fuera de %s (de tus directorios). Puedes actualizar la contraseña de tu clave privadaen las configuraciones personales para recobrar el acceso a tus archivos encriptados.", +"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "No se puede descibrar este archivo, probablemente sea un archivo compartido. Por favor pídele al dueño que recomparta el archivo contigo.", +"Unknown error please check your system settings or contact your administrator" => "Error desconocido, por favor chequea la configuración de tu sistema o contacte a su administrador", "Missing requirements." => "Requisitos incompletos.", "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." => "Por favor, asegúrese de que PHP 5.3.3 o una versión más reciente esté instalado y que OpenSSL junto con la extensión PHP esté habilitado y configurado apropiadamente. Por ahora, la aplicación de encriptación ha sido deshabilitada.", "Following users are not set up for encryption:" => "Los siguientes usuarios no fueron configurados para encriptar:", -"Saving..." => "Guardando...", +"Initial encryption started... This can take some time. Please wait." => "Encriptación inicial comenzada... Esto puede durar un tiempo. Por favor espere.", +"Initial encryption running... Please try again later." => "Encriptación inicial corriendo... Por favor intente mas tarde. ", +"Go directly to your " => "Ve directamente a tu", "personal settings" => "Configuración personal", "Encryption" => "Encriptación", "Enable recovery key (allow to recover users files in case of password loss):" => "Habilitar clave de recuperación (te permite recuperar los archivos de usuario en el caso que pierdas la contraseña):", "Recovery key password" => "Contraseña de recuperación de clave", +"Repeat Recovery key password" => "Repetir la contraseña de la clave de recuperación", "Enabled" => "Habilitado", "Disabled" => "Deshabilitado", "Change recovery key password:" => "Cambiar contraseña para recuperar la clave:", "Old Recovery key password" => "Contraseña antigua de recuperación de clave", "New Recovery key password" => "Nueva contraseña de recuperación de clave", +"Repeat New Recovery key password" => "Repetir Nueva contraseña para la clave de recuperación", "Change Password" => "Cambiar contraseña", "Your private key password no longer match your log-in password:" => "Tu contraseña de clave privada ya no coincide con la contraseña de ingreso:", "Set your old private key password to your current log-in password." => "Usá tu contraseña de clave privada antigua para tu contraseña de ingreso actual.", diff --git a/apps/files_encryption/l10n/es_MX.php b/apps/files_encryption/l10n/es_MX.php index 3906e3cacb..e2915f8e71 100644 --- a/apps/files_encryption/l10n/es_MX.php +++ b/apps/files_encryption/l10n/es_MX.php @@ -16,7 +16,6 @@ $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." => "Por favor, asegúrese de que PHP 5.3.3 o posterior está instalado y que la extensión OpenSSL de PHP está habilitada y configurada correctamente. Por el momento, la aplicación de cifrado ha sido deshabilitada.", "Following users are not set up for encryption:" => "Los siguientes usuarios no han sido configurados para el cifrado:", "Initial encryption started... This can take some time. Please wait." => "Encriptación iniciada... Esto puede tomar un tiempo. Por favor espere.", -"Saving..." => "Guardando...", "Go directly to your " => "Ir directamente a su", "personal settings" => "opciones personales", "Encryption" => "Cifrado", diff --git a/apps/files_encryption/l10n/et_EE.php b/apps/files_encryption/l10n/et_EE.php index 9182c5ef19..f82f9df927 100644 --- a/apps/files_encryption/l10n/et_EE.php +++ b/apps/files_encryption/l10n/et_EE.php @@ -16,7 +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.", -"Saving..." => "Salvestamine...", +"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/eu.php b/apps/files_encryption/l10n/eu.php index 6b1bafdda1..9d51ebba2b 100644 --- a/apps/files_encryption/l10n/eu.php +++ b/apps/files_encryption/l10n/eu.php @@ -16,7 +16,6 @@ $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." => "Mesedez ziurtatu PHP 5.3.3 edo berriago bat instalatuta dagoela eta OpenSSL PHP hedapenarekin gaitua eta ongi konfiguratuta dagoela. Oraingoz, enkriptazio aplikazioa desgaituta dago.", "Following users are not set up for encryption:" => "Hurrengo erabiltzaileak ez daude enktriptatzeko konfiguratutak:", "Initial encryption started... This can take some time. Please wait." => "Hasierako enkriptazioa hasi da... Honek denbora har dezake. Mesedez itxaron.", -"Saving..." => "Gordetzen...", "Go directly to your " => "Joan zuzenean zure", "personal settings" => "ezarpen pertsonalak", "Encryption" => "Enkriptazioa", diff --git a/apps/files_encryption/l10n/fa.php b/apps/files_encryption/l10n/fa.php index ed044a4158..3f8d631e10 100644 --- a/apps/files_encryption/l10n/fa.php +++ b/apps/files_encryption/l10n/fa.php @@ -9,7 +9,6 @@ $TRANSLATIONS = array( "Private key password successfully updated." => "رمزعبور کلید خصوصی با موفقیت به روز شد.", "Could not update the private key password. Maybe the old password was not correct." => "رمزعبور کلید خصوصی را نمی تواند به روز کند. شاید رمزعبور قدیمی صحیح نمی باشد.", "Missing requirements." => "نیازمندی های گمشده", -"Saving..." => "در حال ذخیره سازی...", "personal settings" => "تنظیمات شخصی", "Encryption" => "رمزگذاری", "Enable recovery key (allow to recover users files in case of password loss):" => "فعال کردن کلید بازیابی(اجازه بازیابی فایل های کاربران در صورت از دست دادن رمزعبور):", diff --git a/apps/files_encryption/l10n/fi_FI.php b/apps/files_encryption/l10n/fi_FI.php index b3df41b1f4..6a0025cd98 100644 --- a/apps/files_encryption/l10n/fi_FI.php +++ b/apps/files_encryption/l10n/fi_FI.php @@ -3,8 +3,8 @@ $TRANSLATIONS = array( "Recovery key successfully enabled" => "Palautusavain kytketty päälle onnistuneesti", "Password successfully changed." => "Salasana vaihdettiin onnistuneesti.", "Could not change the password. Maybe the old password was not correct." => "Salasanan vaihto epäonnistui. Kenties vanha salasana oli väärin.", +"Private key password successfully updated." => "Yksityisen avaimen salasana päivitetty onnistuneesti.", "Following users are not set up for encryption:" => "Seuraavat käyttäjät eivät ole määrittäneet salausta:", -"Saving..." => "Tallennetaan...", "personal settings" => "henkilökohtaiset asetukset", "Encryption" => "Salaus", "Recovery key password" => "Palautusavaimen salasana", diff --git a/apps/files_encryption/l10n/fr.php b/apps/files_encryption/l10n/fr.php index dbccbf74dc..a68b6a7132 100644 --- a/apps/files_encryption/l10n/fr.php +++ b/apps/files_encryption/l10n/fr.php @@ -16,7 +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." => "Veuillez vous assurer qu'une version de PHP 5.3.3 ou supérieure est installée et qu'OpenSSL et son extension PHP sont activés et configurés correctement. En attendant, l'application de chiffrement été désactivée.", "Following users are not set up for encryption:" => "Les utilisateurs suivants ne sont pas configurés pour le chiffrement :", "Initial encryption started... This can take some time. Please wait." => "Chiffrement initial démarré... Cela peut prendre un certain temps. Veuillez patienter.", -"Saving..." => "Enregistrement...", +"Initial encryption running... Please try again later." => "Chiffrement initial en cours... Veuillez re-essayer ultérieurement.", "Go directly to your " => "Allez directement à votre", "personal settings" => "paramètres personnel", "Encryption" => "Chiffrement", diff --git a/apps/files_encryption/l10n/gl.php b/apps/files_encryption/l10n/gl.php index 7b3c899d1f..08567ef276 100644 --- a/apps/files_encryption/l10n/gl.php +++ b/apps/files_encryption/l10n/gl.php @@ -16,7 +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." => "Asegúrese de que está instalado o PHP 5.3.3 ou posterior e de o OpenSSL xunto coa extensión PHP estean activados e configurados correctamente. Polo de agora foi desactivado o aplicativo de cifrado.", "Following users are not set up for encryption:" => "Os seguintes usuarios non teñen configuración para o cifrado:", "Initial encryption started... This can take some time. Please wait." => "Comezou o cifrado inicial... Isto pode levar bastante tempo. Agarde.", -"Saving..." => "Gardando...", +"Initial encryption running... Please try again later." => "O cifrado inicial está en execución... Tenteo máis tarde.", "Go directly to your " => "Vaia directamente ao seu", "personal settings" => "axustes persoais", "Encryption" => "Cifrado", diff --git a/apps/files_encryption/l10n/he.php b/apps/files_encryption/l10n/he.php index cdf29c9b0a..ca8783d196 100644 --- a/apps/files_encryption/l10n/he.php +++ b/apps/files_encryption/l10n/he.php @@ -1,6 +1,5 @@ "שמירה…", "Encryption" => "הצפנה" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/hu_HU.php b/apps/files_encryption/l10n/hu_HU.php index 163011ff80..22c1fa989b 100644 --- a/apps/files_encryption/l10n/hu_HU.php +++ b/apps/files_encryption/l10n/hu_HU.php @@ -16,7 +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.", -"Saving..." => "Mentés...", +"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/id.php b/apps/files_encryption/l10n/id.php index a719d44582..a4c3ae547c 100644 --- a/apps/files_encryption/l10n/id.php +++ b/apps/files_encryption/l10n/id.php @@ -13,7 +13,6 @@ $TRANSLATIONS = array( "Missing requirements." => "Persyaratan yang hilang.", "Following users are not set up for encryption:" => "Pengguna berikut belum diatur untuk enkripsi:", "Initial encryption started... This can take some time. Please wait." => "Inisial enskripsi dijalankan... Ini dapat memakan waktu. Silakan tunggu.", -"Saving..." => "Menyimpan...", "Go directly to your " => "Langsung ke anda", "personal settings" => "pengaturan pribadi", "Encryption" => "Enkripsi", diff --git a/apps/files_encryption/l10n/is.php b/apps/files_encryption/l10n/is.php index 27c0904a53..7b7a403b46 100644 --- a/apps/files_encryption/l10n/is.php +++ b/apps/files_encryption/l10n/is.php @@ -1,6 +1,5 @@ "Er að vista ...", "Encryption" => "Dulkóðun" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/it.php b/apps/files_encryption/l10n/it.php index fc1aaffc02..42ee846a76 100644 --- a/apps/files_encryption/l10n/it.php +++ b/apps/files_encryption/l10n/it.php @@ -16,7 +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." => "Assicurati che sia installato PHP 5.3.3 o versioni successive e che l'estensione OpenSSL di PHP sia abilitata e configurata correttamente. Per ora, l'applicazione di cifratura è disabilitata.", "Following users are not set up for encryption:" => "I seguenti utenti non sono configurati per la cifratura:", "Initial encryption started... This can take some time. Please wait." => "Cifratura iniziale avviata... Potrebbe richiedere del tempo. Attendi.", -"Saving..." => "Salvataggio in corso...", +"Initial encryption running... Please try again later." => "Cifratura iniziale in esecuzione... Riprova più tardi.", "Go directly to your " => "Passa direttamente a", "personal settings" => "impostazioni personali", "Encryption" => "Cifratura", diff --git a/apps/files_encryption/l10n/ja.php b/apps/files_encryption/l10n/ja.php new file mode 100644 index 0000000000..476566e00f --- /dev/null +++ b/apps/files_encryption/l10n/ja.php @@ -0,0 +1,44 @@ + "リカバリ用のキーを正常に有効にしました", +"Could not enable recovery key. Please check your recovery key password!" => "リカバリ用のキーを有効にできませんでした。リカバリ用のキーのパスワードを確認してください!", +"Recovery key successfully disabled" => "リカバリ用のキーを正常に無効化しました", +"Could not disable recovery key. Please check your recovery key password!" => "リカバリ用のキーを無効化できませんでした。リカバリ用のキーのパスワードを確認してください!", +"Password successfully changed." => "パスワードを変更できました。", +"Could not change the password. Maybe the old password was not correct." => "パスワードを変更できませんでした。古いパスワードが間違っているかもしれません。", +"Private key password successfully updated." => "秘密鍵のパスワードが正常に更新されました。", +"Could not update the private key password. Maybe the old password was not correct." => "秘密鍵のパスワードを更新できませんでした。古いパスワードが正確でない場合があります。", +"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "セッション中に暗号化アプリを再度有効にされたため、暗号化アプリが初期化されていません。暗号化アプリを初期化するため、ログアウトしてログインしなおしてください。", +"Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "プライベートキーが有効ではありません!パスワードが%sの外部で変更された(例: 共同ディレクトリ)と思われます。個人設定でプライベートキーのパスワードを更新して、暗号化ファイルへのアクセスを回復することができます。", +"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "このファイルを復号化できません、共有ファイルの可能性があります。ファイルの所有者にお願いして、ファイルを共有しなおしてもらってください。", +"Unknown error please check your system settings or contact your administrator" => "不明なエラーです。システム設定を確認するか、管理者に問い合わせてください。", +"Missing requirements." => "必要要件が満たされていません。", +"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拡張を有効にした上でOpenSSLも同様にインストール、適切に設定してください。現時点では暗号化アプリは無効になっています。", +"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" => "暗号化", +"Enable recovery key (allow to recover users files in case of password loss):" => "リカバリキーを有効にする (パスワードを忘れた場合にユーザーのファイルを回復できます):", +"Recovery key password" => "リカバリキーのパスワード", +"Repeat Recovery key password" => "リカバリキーのパスワードをもう一度入力", +"Enabled" => "有効", +"Disabled" => "無効", +"Change recovery key password:" => "リカバリキーのパスワードを変更:", +"Old Recovery key password" => "古いリカバリキーのパスワード", +"New Recovery key password" => "新しいリカバリキーのパスワード", +"Repeat New Recovery key password" => "新しいリカバリキーのパスワードをもう一度入力", +"Change Password" => "パスワードを変更", +"Your private key password no longer match your log-in password:" => "もはや秘密鍵はログインパスワードと一致しません:", +"Set your old private key password to your current log-in password." => "古い秘密鍵のパスワードを現在のログインパスワードに設定する。", +" If you don't remember your old password you can ask your administrator to recover your files." => "古いパスワードを覚えていない場合、管理者に尋ねてファイルを回復することができます。", +"Old log-in password" => "古いログインパスワード", +"Current log-in password" => "現在のログインパスワード", +"Update Private Key Password" => "秘密鍵のパスワードを更新", +"Enable password recovery:" => "パスワードリカバリを有効に:", +"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "このオプションを有効にすると、パスワードを紛失した場合も、暗号化されたファイルに再度アクセスすることができるようになります。", +"File recovery settings updated" => "ファイルリカバリ設定を更新しました", +"Could not update file recovery" => "ファイルリカバリを更新できませんでした" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/ja_JP.php b/apps/files_encryption/l10n/ja_JP.php index 1206969746..476566e00f 100644 --- a/apps/files_encryption/l10n/ja_JP.php +++ b/apps/files_encryption/l10n/ja_JP.php @@ -1,34 +1,34 @@ "リカバリ用のキーは正常に有効化されました", -"Could not enable recovery key. Please check your recovery key password!" => "リカバリ用のキーを有効にできませんでした。リカバリ用のキーのパスワードを確認して下さい!", +"Recovery key successfully enabled" => "リカバリ用のキーを正常に有効にしました", +"Could not enable recovery key. Please check your recovery key password!" => "リカバリ用のキーを有効にできませんでした。リカバリ用のキーのパスワードを確認してください!", "Recovery key successfully disabled" => "リカバリ用のキーを正常に無効化しました", -"Could not disable recovery key. Please check your recovery key password!" => "リカバリ用のキーを無効化できませんでした。リカバリ用のキーのパスワードを確認して下さい!", +"Could not disable recovery key. Please check your recovery key password!" => "リカバリ用のキーを無効化できませんでした。リカバリ用のキーのパスワードを確認してください!", "Password successfully changed." => "パスワードを変更できました。", "Could not change the password. Maybe the old password was not correct." => "パスワードを変更できませんでした。古いパスワードが間違っているかもしれません。", "Private key password successfully updated." => "秘密鍵のパスワードが正常に更新されました。", "Could not update the private key password. Maybe the old password was not correct." => "秘密鍵のパスワードを更新できませんでした。古いパスワードが正確でない場合があります。", -"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "暗号化アプリが初期化されていません。暗号化アプリが接続中に再度有効かされた可能性があります。暗号化アプリを初期化する為に、1回ログアウトしてログインしなおしてください。", +"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "セッション中に暗号化アプリを再度有効にされたため、暗号化アプリが初期化されていません。暗号化アプリを初期化するため、ログアウトしてログインしなおしてください。", "Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "プライベートキーが有効ではありません!パスワードが%sの外部で変更された(例: 共同ディレクトリ)と思われます。個人設定でプライベートキーのパスワードを更新して、暗号化ファイルへのアクセスを回復することができます。", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "このファイルを復号化できません、共有ファイルの可能性があります。ファイルの所有者にお願いして、ファイルを共有しなおしてもらってください。", "Unknown error please check your system settings or contact your administrator" => "不明なエラーです。システム設定を確認するか、管理者に問い合わせてください。", "Missing requirements." => "必要要件が満たされていません。", "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拡張を有効にした上でOpenSSLも同様にインストール、適切に設定してください。現時点では暗号化アプリは無効になっています。", "Following users are not set up for encryption:" => "以下のユーザーは、暗号化設定がされていません:", -"Initial encryption started... This can take some time. Please wait." => "暗号化の初期化作業を開始しました... この処理にはしばらく時間がかかります。今しばらくお待ちください。", -"Saving..." => "保存中...", +"Initial encryption started... This can take some time. Please wait." => "暗号化の初期化作業を開始しました... この処理にはしばらく時間がかかります。お待ちください。", +"Initial encryption running... Please try again later." => "初期暗号化実行中... 後でもう一度お試しください。", "Go directly to your " => "あなたのディレクトリへ", "personal settings" => "秘密鍵をアンロックできます", "Encryption" => "暗号化", -"Enable recovery key (allow to recover users files in case of password loss):" => "復旧キーを有効化 (万一パスワードを亡くした場合もユーザーのファイルを回復できる):", -"Recovery key password" => "復旧キーのパスワード", -"Repeat Recovery key password" => "復旧キーのパスワードをもう一度入力", +"Enable recovery key (allow to recover users files in case of password loss):" => "リカバリキーを有効にする (パスワードを忘れた場合にユーザーのファイルを回復できます):", +"Recovery key password" => "リカバリキーのパスワード", +"Repeat Recovery key password" => "リカバリキーのパスワードをもう一度入力", "Enabled" => "有効", "Disabled" => "無効", -"Change recovery key password:" => "復旧キーのパスワードを変更:", -"Old Recovery key password" => "古い復旧キーのパスワード", -"New Recovery key password" => "新しい復旧キーのパスワード", -"Repeat New Recovery key password" => "新しい復旧キーのパスワードをもう一度入力", +"Change recovery key password:" => "リカバリキーのパスワードを変更:", +"Old Recovery key password" => "古いリカバリキーのパスワード", +"New Recovery key password" => "新しいリカバリキーのパスワード", +"Repeat New Recovery key password" => "新しいリカバリキーのパスワードをもう一度入力", "Change Password" => "パスワードを変更", "Your private key password no longer match your log-in password:" => "もはや秘密鍵はログインパスワードと一致しません:", "Set your old private key password to your current log-in password." => "古い秘密鍵のパスワードを現在のログインパスワードに設定する。", @@ -36,9 +36,9 @@ $TRANSLATIONS = array( "Old log-in password" => "古いログインパスワード", "Current log-in password" => "現在のログインパスワード", "Update Private Key Password" => "秘密鍵のパスワードを更新", -"Enable password recovery:" => "パスワード復旧を有効化:", +"Enable password recovery:" => "パスワードリカバリを有効に:", "Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "このオプションを有効にすると、パスワードを紛失した場合も、暗号化されたファイルに再度アクセスすることができるようになります。", -"File recovery settings updated" => "ファイル復旧設定が更新されました", -"Could not update file recovery" => "ファイル復旧を更新できませんでした" +"File recovery settings updated" => "ファイルリカバリ設定を更新しました", +"Could not update file recovery" => "ファイルリカバリを更新できませんでした" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/ka_GE.php b/apps/files_encryption/l10n/ka_GE.php index bbabd44964..d063463477 100644 --- a/apps/files_encryption/l10n/ka_GE.php +++ b/apps/files_encryption/l10n/ka_GE.php @@ -1,6 +1,5 @@ "შენახვა...", "Encryption" => "ენკრიპცია" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/km.php b/apps/files_encryption/l10n/km.php new file mode 100644 index 0000000000..0defe6c538 --- /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/ko.php b/apps/files_encryption/l10n/ko.php index d91e861ca5..41168a340c 100644 --- a/apps/files_encryption/l10n/ko.php +++ b/apps/files_encryption/l10n/ko.php @@ -16,7 +16,6 @@ $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 이상 설치 여부, PHP의 OpenSSL 확장 기능 활성화 및 설정 여부를 확인하십시오. 암호화 앱이 비활성화 되었습니다.", "Following users are not set up for encryption:" => "다음 사용자는 암호화를 사용할 수 없습니다:", "Initial encryption started... This can take some time. Please wait." => "초기 암호화가 시작되었습니다... 시간이 걸릴 수도 있으니 기다려 주십시오.", -"Saving..." => "저장 중...", "Go directly to your " => "다음으로 바로 가기: ", "personal settings" => "개인 설정", "Encryption" => "암호화", diff --git a/apps/files_encryption/l10n/ku_IQ.php b/apps/files_encryption/l10n/ku_IQ.php index d971350b4c..d7b10d1df6 100644 --- a/apps/files_encryption/l10n/ku_IQ.php +++ b/apps/files_encryption/l10n/ku_IQ.php @@ -1,6 +1,5 @@ "پاشکه‌وتده‌کات...", "Encryption" => "نهێنیکردن" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/lt_LT.php b/apps/files_encryption/l10n/lt_LT.php index 993e03388d..dd8a0d7633 100644 --- a/apps/files_encryption/l10n/lt_LT.php +++ b/apps/files_encryption/l10n/lt_LT.php @@ -9,12 +9,13 @@ $TRANSLATIONS = array( "Private key password successfully updated." => "Privataus rakto slaptažodis buvo sėkmingai atnaujintas.", "Could not update the private key password. Maybe the old password was not correct." => "Nepavyko atnaujinti privataus rakto slaptažodžio. Gali būti, kad buvo neteisingai suvestas senasis.", "Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "Šifravimo programa nepaleista! Galbūt šifravimo programa buvo įjungta dar kartą Jūsų sesijos metu. Prašome atsijungti ir vėl prisijungti, kad paleisti šifravimo programą.", +"Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Jūsų privatus raktas yra netinkamas! Panašu, kad Jūsų slaptažodis buvo pakeistas už %s (pvz. Jūsų organizacijos kataloge). Galite atnaujinti savo privataus rakto slaptažodį savo asmeniniuose nustatymuose, kad atkurti prieigą prie savo šifruotų failų.", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "Failo iššifruoti nepavyko, gali būti jog jis yra pasidalintas su jumis. Paprašykite failo savininko, kad jums iš naujo pateiktų šį failą.", "Unknown error please check your system settings or contact your administrator" => "Neatpažinta klaida, patikrinkite sistemos nustatymus arba kreipkitės į savo sistemos aministratorių", "Missing requirements." => "Trūkstami laukai.", "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." => "Prašome įsitikinti, kad PHP 5.3.3 ar naujesnė yra įdiegta ir kad OpenSSL kartu su PHP plėtiniu yra šjungti ir teisingai sukonfigūruoti. Kol kas šifravimo programa bus išjungta.", "Following users are not set up for encryption:" => "Sekantys naudotojai nenustatyti šifravimui:", -"Saving..." => "Saugoma...", +"Initial encryption started... This can take some time. Please wait." => "Pradėtas pirminis šifravimas... Tai gali užtrukti. Prašome palaukti.", "Go directly to your " => "Eiti tiesiai į Jūsų", "personal settings" => "asmeniniai nustatymai", "Encryption" => "Šifravimas", diff --git a/apps/files_encryption/l10n/lv.php b/apps/files_encryption/l10n/lv.php index b8414174a7..cbf8b7cbda 100644 --- a/apps/files_encryption/l10n/lv.php +++ b/apps/files_encryption/l10n/lv.php @@ -1,6 +1,5 @@ "Saglabā...", "Encryption" => "Šifrēšana" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"; diff --git a/apps/files_encryption/l10n/mk.php b/apps/files_encryption/l10n/mk.php index 098f4d635b..b13d2c28ce 100644 --- a/apps/files_encryption/l10n/mk.php +++ b/apps/files_encryption/l10n/mk.php @@ -3,7 +3,6 @@ $TRANSLATIONS = array( "Password successfully changed." => "Лозинката е успешно променета.", "Could not change the password. Maybe the old password was not correct." => "Лозинката не можеше да се промени. Можеби старата лозинка не беше исправна.", "Missing requirements." => "Барања кои недостасуваат.", -"Saving..." => "Снимам...", "Go directly to your " => "Одете директно на вашиот", "personal settings" => "лични подесувања", "Encryption" => "Енкрипција", diff --git a/apps/files_encryption/l10n/nb_NO.php b/apps/files_encryption/l10n/nb_NO.php index 26956c410a..f7484c0e15 100644 --- a/apps/files_encryption/l10n/nb_NO.php +++ b/apps/files_encryption/l10n/nb_NO.php @@ -1,6 +1,43 @@ "Lagrer...", -"Encryption" => "Kryptering" +"Recovery key successfully enabled" => "Gjenopprettingsnøkkel aktivert", +"Could not enable recovery key. Please check your recovery key password!" => "Klarte ikke å aktivere gjenopprettingsnøkkel. Sjekk passordet for gjenopprettingsnøkkelen.", +"Recovery key successfully disabled" => "Gjenopprettingsnøkkel ble deaktivert", +"Could not disable recovery key. Please check your recovery key password!" => "Klarte ikke å deaktivere gjenopprettingsnøkkel. Sjekk passordet for gjenopprettingsnøkkelen.", +"Password successfully changed." => "Passordet ble endret.", +"Could not change the password. Maybe the old password was not correct." => "Klarte ikke å endre passordet. Kanskje gammelt passord ikke var korrekt.", +"Private key password successfully updated." => "Passord for privat nøkkel ble oppdatert.", +"Could not update the private key password. Maybe the old password was not correct." => "Klarte ikke å oppdatere passord for privat nøkkel. Kanskje gammelt passord ikke var korrekt.", +"Encryption app not initialized! Maybe the encryption app was re-enabled during your session. Please try to log out and log back in to initialize the encryption app." => "Krypterings-app ikke initialisert! Kanskje krypterings-appen ble aktivert på nytt i løpet av økten din. Prøv å logge ut og logge inn igjen for å initialisere krypterings-appen.", +"Your private key is not valid! Likely your password was changed outside of %s (e.g. your corporate directory). You can update your private key password in your personal settings to recover access to your encrypted files." => "Din private nøkkel er ikke gyldig! Sannsynligvis ble passordet ditt endret utenfor %s. (f.eks. din bedriftskatalog). Du kan oppdatere passordet for din private nøkkel i dine personlige innstillinger for å gjenvinne tilgang til de krypterte filene dine.", +"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "Kan ikke dekryptere denne filen. Dette er sannsynligvis en delt fil. Spør eieren av filen om å dele den med deg på nytt.", +"Unknown error please check your system settings or contact your administrator" => "Ukjent feil. Sjekk systeminnstillingene dine eller kontakt administratoren", +"Missing requirements." => "Manglende krav.", +"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." => "Vennligst se til at PHP 5.3.3 eller nyere er installert og at OpenSSL sammen med PHP-utvidelsen er aktivert og riktig konfigurert. Enn så lenge er krypterings-appen deaktivert.", +"Following users are not set up for encryption:" => "Følgende brukere er ikke satt opp for kryptering:", +"Initial encryption started... This can take some time. Please wait." => "Første gangs kryptering startet... Dette kan ta litt tid. Vennligst vent.", +"Go directly to your " => "Gå direkte til din", +"personal settings" => "personlige innstillinger", +"Encryption" => "Kryptering", +"Enable recovery key (allow to recover users files in case of password loss):" => "Aktiver gjenopprettingsnøkkel (tillat å gjenopprette brukerfiler i tilfelle tap av passord):", +"Recovery key password" => "Passord for gjenopprettingsnøkkel", +"Repeat Recovery key password" => "Gjenta passord for gjenopprettingsnøkkel", +"Enabled" => "Aktiv", +"Disabled" => "Inaktiv", +"Change recovery key password:" => "Endre passord for gjenopprettingsnøkkel:", +"Old Recovery key password" => "Gammelt passord for gjenopprettingsnøkkel", +"New Recovery key password" => "Nytt passord for gjenopprettingsnøkkel", +"Repeat New Recovery key password" => "Gjenta nytt passord for gjenopprettingsnøkkel", +"Change Password" => "Endre passord", +"Your private key password no longer match your log-in password:" => "Ditt passord for privat nøkkel stemmer ikke med påloggingspassordet ditt lenger:", +"Set your old private key password to your current log-in password." => "Sett ditt gamle passord for privat nøkkel til ditt nåværende påloggingspassord.", +" If you don't remember your old password you can ask your administrator to recover your files." => "Hvis du ikke husker det gamle passordet ditt kan du spørre administratoren om å gjenopprette filene dine.", +"Old log-in password" => "Gammelt påloggingspassord", +"Current log-in password" => "Nåværende påloggingspassord", +"Update Private Key Password" => "Oppdater passord for privat nøkkel", +"Enable password recovery:" => "Aktiver gjenoppretting av passord:", +"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Aktivering av dette valget tillater deg å gjenerobre tilgang til dine krypterte filer i tilfelle du mister passordet ditt.", +"File recovery settings updated" => "Innstillinger for gjenoppretting av filer ble oppdatert", +"Could not update file recovery" => "Klarte ikke å oppdatere gjenoppretting av filer" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/nl.php b/apps/files_encryption/l10n/nl.php index 081e46a785..e878fc6c12 100644 --- a/apps/files_encryption/l10n/nl.php +++ b/apps/files_encryption/l10n/nl.php @@ -16,7 +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." => "Wees er zeker van dat PHP5.3.3 of nieuwer is geïstalleerd en dat de OpenSSL PHP extensie is ingeschakeld en correct geconfigureerd. De versleutel-app is voorlopig uitgeschakeld.", "Following users are not set up for encryption:" => "De volgende gebruikers hebben geen configuratie voor encryptie:", "Initial encryption started... This can take some time. Please wait." => "initiële versleuteling gestart... Dit kan even duren, geduld a.u.b.", -"Saving..." => "Opslaan", +"Initial encryption running... Please try again later." => "Initiële versleuteling bezig... Probeer het later opnieuw.", "Go directly to your " => "Ga meteen naar uw", "personal settings" => "persoonlijke instellingen", "Encryption" => "Versleuteling", diff --git a/apps/files_encryption/l10n/nn_NO.php b/apps/files_encryption/l10n/nn_NO.php index bb30d69c59..c472655c8b 100644 --- a/apps/files_encryption/l10n/nn_NO.php +++ b/apps/files_encryption/l10n/nn_NO.php @@ -1,6 +1,5 @@ "Lagrar …", "Encryption" => "Kryptering" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/pl.php b/apps/files_encryption/l10n/pl.php index b768bd46f8..db2a02cec9 100644 --- a/apps/files_encryption/l10n/pl.php +++ b/apps/files_encryption/l10n/pl.php @@ -16,7 +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." => "Proszę upewnić się, że PHP 5.3.3 lub nowszy jest zainstalowany i że OpenSSL oraz rozszerzenie PHP jest włączone i poprawnie skonfigurowane. Obecnie szyfrowanie aplikacji zostało wyłączone.", "Following users are not set up for encryption:" => "Następujący użytkownicy nie mają skonfigurowanego szyfrowania:", "Initial encryption started... This can take some time. Please wait." => "Rozpoczęto szyfrowanie... To może chwilę potrwać. Proszę czekać.", -"Saving..." => "Zapisywanie...", +"Initial encryption running... Please try again later." => "Trwa szyfrowanie początkowe...Spróbuj ponownie.", "Go directly to your " => "Przejdź bezpośrednio do", "personal settings" => "Ustawienia osobiste", "Encryption" => "Szyfrowanie", diff --git a/apps/files_encryption/l10n/pt_BR.php b/apps/files_encryption/l10n/pt_BR.php index 2fce7fd13a..204311658a 100644 --- a/apps/files_encryption/l10n/pt_BR.php +++ b/apps/files_encryption/l10n/pt_BR.php @@ -16,7 +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." => "Por favor, certifique-se que o PHP 5.3.3 ou mais recente está instalado e que a extensão PHP OpenSSL está habilitado e configurado corretamente. Por enquanto, o aplicativo de criptografia foi desativado.", "Following users are not set up for encryption:" => "Seguintes usuários não estão configurados para criptografia:", "Initial encryption started... This can take some time. Please wait." => "Criptografia inicial inicializada... Isto pode tomar algum tempo. Por favor espere.", -"Saving..." => "Salvando...", +"Initial encryption running... Please try again later." => "Criptografia inicial em execução ... Por favor, tente novamente mais tarde.", "Go directly to your " => "Ir diretamente para o seu", "personal settings" => "configurações pessoais.", "Encryption" => "Criptografia", diff --git a/apps/files_encryption/l10n/pt_PT.php b/apps/files_encryption/l10n/pt_PT.php index 77424005c3..9a1963953e 100644 --- a/apps/files_encryption/l10n/pt_PT.php +++ b/apps/files_encryption/l10n/pt_PT.php @@ -7,9 +7,11 @@ $TRANSLATIONS = array( "Password successfully changed." => "Password alterada com sucesso.", "Could not change the password. Maybe the old password was not correct." => "Não foi possivel alterar a password. Possivelmente a password antiga não está correcta.", "Could not update the private key password. Maybe the old password was not correct." => "Não foi possível alterar a chave. Possivelmente a password antiga não está correcta.", +"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "Não foi possível desencriptar este ficheiro, possivelmente é um ficheiro partilhado. Peça ao proprietário do ficheiro para voltar a partilhar o ficheiro consigo.", +"Unknown error please check your system settings or contact your administrator" => "Erro desconhecido. Verifique por favor as definições do sistema ou contacte o seu administrador", "Missing requirements." => "Faltam alguns requisitos.", "Following users are not set up for encryption:" => "Os utilizadores seguintes não estão marcados para cifragem:", -"Saving..." => "A guardar...", +"Go directly to your " => "Ir directamente para o seu", "personal settings" => "configurações personalizadas ", "Encryption" => "Encriptação", "Enable recovery key (allow to recover users files in case of password loss):" => "Active a chave de recuperação (permite recuperar os ficheiros no caso de perda da password):", diff --git a/apps/files_encryption/l10n/ro.php b/apps/files_encryption/l10n/ro.php index 3dcdce3241..5aabc49864 100644 --- a/apps/files_encryption/l10n/ro.php +++ b/apps/files_encryption/l10n/ro.php @@ -1,6 +1,20 @@ "Se salvează...", -"Encryption" => "Încriptare" +"Recovery key successfully enabled" => "Cheia de recupeare a fost activata cu succes", +"Could not enable recovery key. Please check your recovery key password!" => "Nu s-a putut activa cheia de recuperare. Verifica parola de recuperare!", +"Recovery key successfully disabled" => "Cheia de recuperare dezactivata cu succes", +"Could not disable recovery key. Please check your recovery key password!" => "Nu am putut dezactiva cheia de recuperare. Verifica parola de recuperare!", +"Password successfully changed." => "Parola a fost modificată cu succes.", +"Could not change the password. Maybe the old password was not correct." => "Parola nu a putut fi schimbata. Poate ca parola veche este incorecta.", +"Private key password successfully updated." => "Cheia privata a fost actualizata cu succes", +"Could not update the private key password. Maybe the old password was not correct." => "Nu am putut actualiza parola pentru cheia privata. Poate ca parola veche este incorecta.", +"personal settings" => "setari personale", +"Encryption" => "Încriptare", +"Enabled" => "Activat", +"Disabled" => "Dezactivat", +"Change Password" => "Schimbă parola", +"Your private key password no longer match your log-in password:" => "Parola cheii private nu se mai potriveste cu parola ta de logare:", +"File recovery settings updated" => "Setarile pentru recuperarea fisierelor au fost actualizate", +"Could not update file recovery" => "Nu am putut actualiza recuperarea de fisiere" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"; diff --git a/apps/files_encryption/l10n/ru.php b/apps/files_encryption/l10n/ru.php index e9744b3db4..ba98486893 100644 --- a/apps/files_encryption/l10n/ru.php +++ b/apps/files_encryption/l10n/ru.php @@ -16,7 +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." => "Начато начальное шифрование... Это может занять какое-то время. Пожалуйста, подождите.", -"Saving..." => "Сохранение...", +"Initial encryption running... Please try again later." => "Работает первоначальное шифрование... Пожалуйста, повторите попытку позже.", "Go directly to your " => "Перейти прямо в", "personal settings" => "персональные настройки", "Encryption" => "Шифрование", diff --git a/apps/files_encryption/l10n/si_LK.php b/apps/files_encryption/l10n/si_LK.php index 5f5330df54..4c7dc957bf 100644 --- a/apps/files_encryption/l10n/si_LK.php +++ b/apps/files_encryption/l10n/si_LK.php @@ -1,6 +1,5 @@ "සුරැකෙමින් පවතී...", "Encryption" => "ගුප්ත කේතනය" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/sk_SK.php b/apps/files_encryption/l10n/sk_SK.php index 9e2c01eba3..53ee2bc030 100644 --- a/apps/files_encryption/l10n/sk_SK.php +++ b/apps/files_encryption/l10n/sk_SK.php @@ -16,7 +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." => "Prosím uistite sa, že PHP verzie 5.3.3 alebo novšej je nainštalované a tiež, že OpenSSL knižnica spolu z PHP rozšírením je povolená a konfigurovaná správne. Nateraz bola aplikácia šifrovania zablokovaná.", "Following users are not set up for encryption:" => "Nasledujúci používatelia nie sú nastavení pre šifrovanie:", "Initial encryption started... This can take some time. Please wait." => "Počiatočné šifrovanie započalo ... To môže nejakú dobu trvať. Čakajte prosím.", -"Saving..." => "Ukladám...", +"Initial encryption running... Please try again later." => "Počiatočné šifrovanie beží... Skúste to neskôr znovu.", "Go directly to your " => "Choďte priamo do vášho", "personal settings" => "osobné nastavenia", "Encryption" => "Šifrovanie", diff --git a/apps/files_encryption/l10n/sl.php b/apps/files_encryption/l10n/sl.php index 60faf34cf8..e581f9323c 100644 --- a/apps/files_encryption/l10n/sl.php +++ b/apps/files_encryption/l10n/sl.php @@ -16,7 +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." => "Preverite, ali je na strežniku nameščen paket PHP 5.3.3 ali novejši, da je omogočen in pravilno nastavljen PHP OpenSSL. Z obstoječimi možnostmi šifriranje ni mogoče.", "Following users are not set up for encryption:" => "Navedeni uporabniki še nimajo nastavljenega šifriranja:", "Initial encryption started... This can take some time. Please wait." => "Začetno šifriranje je začeto ... Opravilo je lahko dolgotrajno.", -"Saving..." => "Poteka shranjevanje ...", +"Initial encryption running... Please try again later." => "Začetno šifriranje je v teku ... Poskusite kasneje.", "Go directly to your " => "Skočite neposredno na", "personal settings" => "osebne nastavitve", "Encryption" => "Šifriranje", diff --git a/apps/files_encryption/l10n/sr.php b/apps/files_encryption/l10n/sr.php index cbf87dcf4d..8a291faed2 100644 --- a/apps/files_encryption/l10n/sr.php +++ b/apps/files_encryption/l10n/sr.php @@ -1,6 +1,5 @@ "Чување у току...", "Encryption" => "Шифровање" ); $PLURAL_FORMS = "nplurals=3; 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_encryption/l10n/sv.php b/apps/files_encryption/l10n/sv.php index 1e509ea08e..b17740f254 100644 --- a/apps/files_encryption/l10n/sv.php +++ b/apps/files_encryption/l10n/sv.php @@ -15,7 +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:", -"Saving..." => "Sparar...", +"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/l10n/ta_LK.php b/apps/files_encryption/l10n/ta_LK.php index 9dec6de3ac..327102b5df 100644 --- a/apps/files_encryption/l10n/ta_LK.php +++ b/apps/files_encryption/l10n/ta_LK.php @@ -1,6 +1,5 @@ "சேமிக்கப்படுகிறது...", "Encryption" => "மறைக்குறியீடு" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/th_TH.php b/apps/files_encryption/l10n/th_TH.php index 7bf3e2765a..cc670e425a 100644 --- a/apps/files_encryption/l10n/th_TH.php +++ b/apps/files_encryption/l10n/th_TH.php @@ -1,6 +1,5 @@ "กำลังบันทึกข้อมูล...", "Encryption" => "การเข้ารหัส" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/tr.php b/apps/files_encryption/l10n/tr.php index b8289ab71f..85e35f5ddd 100644 --- a/apps/files_encryption/l10n/tr.php +++ b/apps/files_encryption/l10n/tr.php @@ -16,7 +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 veya daha sürümü ile birlikte OpenSSL ve OpenSSL PHP uzantısının birlikte etkin olduğunu ve doğru bir şekilde yapılandırıldığından emin olun. Şimdilik şifreleme uygulaması devre dışı bırakıldı", "Following users are not set up for encryption:" => "Aşağıdaki kullanıcılar şifreleme için ayarlanmadılar:", "Initial encryption started... This can take some time. Please wait." => "İlk şifreleme başladı... Bu biraz zaman alabilir. Lütfen bekleyin.", -"Saving..." => "Kaydediliyor...", +"Initial encryption running... Please try again later." => "İlk şifreleme çalışıyor... Lütfen daha sonra tekrar deneyin.", "Go directly to your " => "Doğrudan şuraya gidin:", "personal settings" => "kişisel ayarlar", "Encryption" => "Şifreleme", diff --git a/apps/files_encryption/l10n/ug.php b/apps/files_encryption/l10n/ug.php index 25b3f68634..da9144bb93 100644 --- a/apps/files_encryption/l10n/ug.php +++ b/apps/files_encryption/l10n/ug.php @@ -1,6 +1,5 @@ "ساقلاۋاتىدۇ…", "Encryption" => "شىفىرلاش" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/uk.php b/apps/files_encryption/l10n/uk.php index 5260dd3f2f..e406c09228 100644 --- a/apps/files_encryption/l10n/uk.php +++ b/apps/files_encryption/l10n/uk.php @@ -1,6 +1,5 @@ "Зберігаю...", "personal settings" => "особисті налаштування", "Encryption" => "Шифрування", "Change Password" => "Змінити Пароль" diff --git a/apps/files_encryption/l10n/vi.php b/apps/files_encryption/l10n/vi.php index 18882be63a..c752f0af22 100644 --- a/apps/files_encryption/l10n/vi.php +++ b/apps/files_encryption/l10n/vi.php @@ -1,11 +1,27 @@ "Khóa khôi phục kích hoạt thành công", +"Could not enable recovery key. Please check your recovery key password!" => "Không thể kích hoạt khóa khôi phục. Vui lòng kiểm tra mật khẩu khóa khôi phục!", +"Recovery key successfully disabled" => "Vô hiệu hóa khóa khôi phục thành công", +"Could not disable recovery key. Please check your recovery key password!" => "Không thể vô hiệu hóa khóa khôi phục. Vui lòng kiểm tra mật khẩu khóa khôi phục!", "Password successfully changed." => "Đã đổi mật khẩu.", "Could not change the password. Maybe the old password was not correct." => "Không thể đổi mật khẩu. Có lẽ do mật khẩu cũ không đúng.", -"Saving..." => "Đang lưu...", +"Private key password successfully updated." => "Cập nhật thành công mật khẩu khóa cá nhân", +"Could not update the private key password. Maybe the old password was not correct." => "Không thể cập nhật mật khẩu khóa cá nhân. Có thể mật khẩu cũ không đúng", +"personal settings" => "Thiết lập cá nhân", "Encryption" => "Mã hóa", "Enabled" => "Bật", "Disabled" => "Tắt", -"Change Password" => "Đổi Mật khẩu" +"Change Password" => "Đổi Mật khẩu", +"Your private key password no longer match your log-in password:" => "Mật khẩu khóa cá nhân không còn phù hợp với mật khẩu đăng nhập:", +"Set your old private key password to your current log-in password." => "Thiết lập mật khẩu khóa cá nhân cũ đến mật khẩu đăng nhập hiện tại.", +" If you don't remember your old password you can ask your administrator to recover your files." => "Nếu bạn không nhớ mật khẩu cũ, bạn có thể yêu cầu quản trị viên khôi phục tập tin của bạn.", +"Old log-in password" => "Mật khẩu đăng nhập cũ", +"Current log-in password" => "Mật khẩu đăng nhập hiện tại", +"Update Private Key Password" => "Cập nhật mật khẩu khóa cá nhân", +"Enable password recovery:" => "Kích hoạt khôi phục mật khẩu:", +"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Tùy chọn này sẽ cho phép bạn tái truy cập đến các tập tin mã hóa trong trường hợp mất mật khẩu", +"File recovery settings updated" => "Đã cập nhật thiết lập khôi phục tập tin ", +"Could not update file recovery" => "Không thể cập nhật khôi phục tập tin" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_encryption/l10n/zh_CN.php b/apps/files_encryption/l10n/zh_CN.php index a51856aec9..4d277e9b17 100644 --- a/apps/files_encryption/l10n/zh_CN.php +++ b/apps/files_encryption/l10n/zh_CN.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Could not change the password. Maybe the old password was not correct." => "不能修改密码。旧密码可能不正确。", "Private key password successfully updated." => "私钥密码成功更新。", "Could not update the private key password. Maybe the old password was not correct." => "无法更新私钥密码。可能旧密码不正确。", -"Saving..." => "保存中", "personal settings" => "个人设置", "Encryption" => "加密", "Enable recovery key (allow to recover users files in case of password loss):" => "启用恢复密钥(允许你在密码丢失后恢复文件):", diff --git a/apps/files_encryption/l10n/zh_TW.php b/apps/files_encryption/l10n/zh_TW.php index 8972490ea5..84146437ac 100644 --- a/apps/files_encryption/l10n/zh_TW.php +++ b/apps/files_encryption/l10n/zh_TW.php @@ -15,7 +15,8 @@ $TRANSLATIONS = array( "Missing requirements." => "遺失必要條件。", "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:" => "以下的使用者無法設定加密:", -"Saving..." => "儲存中...", +"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/lib/crypt.php b/apps/files_encryption/lib/crypt.php index caca13acec..a4f7bd3549 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/helper.php b/apps/files_encryption/lib/helper.php index ef3775875f..8cbbe8a45a 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -367,9 +367,14 @@ class Helper { $post = 0; if(count($_POST) > 0) { $post = 1; - } - header('Location: ' . $location . '?p=' . $post . '&errorCode=' . $errorCode); - exit(); + } + + if(defined('PHPUNIT_RUN') and PHPUNIT_RUN) { + throw new \Exception("Encryption error: $errorCode"); + } + + header('Location: ' . $location . '?p=' . $post . '&errorCode=' . $errorCode); + exit(); } /** diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 9d456f6c51..7be82c313e 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,36 +37,41 @@ 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); + $session = new Session(new \OC\Files\View()); - if (\OCP\App::isEnabled('files_encryption') === false || Crypt::mode() !== 'server' || - strpos($path, '/' . $userId . '/files') !== 0) { + // don't call the crypt stream wrapper, if... + if ( + $session->getInitialized() !== Session::INIT_SUCCESSFUL // encryption successful initialized + || 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', '')); - } + $view = new \OC_FilesystemView(''); + $util = new Util($view, $userId); - if (Crypt::isCatfileContent($path)) { - return true; - } - - $extension = substr($path, strrpos($path, '.') + 1); - - 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; } @@ -127,6 +133,8 @@ class Proxy extends \OC_FileProxy { // re-enable proxy - our work is done \OC_FileProxy::$enabled = $proxyStatus; + } else { + return false; } } } @@ -146,7 +154,7 @@ class Proxy extends \OC_FileProxy { if ( isset(self::$unencryptedSizes[$normalizedPath]) ) { $view = new \OC_FilesystemView('/'); $view->putFileInfo($normalizedPath, - array('encrypted' => true, 'encrypted_size' => self::$unencryptedSizes[$normalizedPath])); + array('encrypted' => true, 'unencrypted_size' => self::$unencryptedSizes[$normalizedPath])); unset(self::$unencryptedSizes[$normalizedPath]); } @@ -204,15 +212,18 @@ class Proxy extends \OC_FileProxy { } /** - * @param $path - * @return bool + * @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 postTouch($path) { - $this->handleFile($path); + public function preFopen($path, $mode) { + + self::$fopenMode[$path] = $mode; + self::$enableEncryption = self::shouldEncrypt($path, $mode); - return true; } + /** * @param $path * @param $result @@ -222,54 +233,28 @@ 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; + // if we remember the mode from the pre proxy we re-use it + // otherwise we fall back to stream_get_meta_data() + if (isset(self::$fopenMode[$path])) { + $mode = self::$fopenMode[$path]; + unset(self::$fopenMode[$path]); + } else { + $meta = stream_get_meta_data($result); + $mode = $meta['mode']; } - // Disable encryption proxy to prevent recursive calls - $proxyStatus = \OC_FileProxy::$enabled; - \OC_FileProxy::$enabled = false; + // Close the original encrypted file + fclose($result); - $meta = stream_get_meta_data($result); - - $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); - - // Open the file using the crypto stream wrapper - // protocol and let it do the decryption work instead - $result = fopen('crypt://' . $path, $meta['mode']); - - } elseif ( - self::shouldEncrypt($path) - and $meta['mode'] !== 'r' - and $meta['mode'] !== 'rb' - ) { - $result = fopen('crypt://' . $path, $meta['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; @@ -320,6 +305,13 @@ class Proxy extends \OC_FileProxy { // if path is a folder do nothing if ($view->is_dir($path)) { + $proxyState = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + $fileInfo = $view->getFileInfo($path); + \OC_FileProxy::$enabled = $proxyState; + if (isset($fileInfo['unencrypted_size']) && $fileInfo['unencrypted_size'] > 0) { + return $fileInfo['unencrypted_size']; + } return $size; } @@ -348,26 +340,24 @@ class Proxy extends \OC_FileProxy { $fileInfo['unencrypted_size'] = $fixSize; // put file info if not .part file if (!Helper::isPartialFilePath($relativePath)) { - $view->putFileInfo($path, $fileInfo); + $view->putFileInfo($path, array('unencrypted_size' => $fixSize)); } } $size = $fileInfo['unencrypted_size']; } else { - // self healing if file was removed from file cache - if (!$fileInfo) { - $fileInfo = array(); - } + + $fileInfoUpdates = array(); $fixSize = $util->getFileSize($path); if ($fixSize > 0) { $size = $fixSize; - $fileInfo['encrypted'] = true; - $fileInfo['unencrypted_size'] = $size; + $fileInfoUpdates['encrypted'] = true; + $fileInfoUpdates['unencrypted_size'] = $size; // put file info if not .part file if (!Helper::isPartialFilePath($relativePath)) { - $view->putFileInfo($path, $fileInfo); + $view->putFileInfo($path, $fileInfoUpdates); } } @@ -375,39 +365,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/session.php b/apps/files_encryption/lib/session.php index aa58e33e9d..3daaa06425 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -134,6 +134,14 @@ class Session { } + /** + * @brief remove encryption keys and init status from session + */ + public function closeSession() { + \OC::$session->remove('encryptionInitialized'); + \OC::$session->remove('privateKey'); + } + /** * @brief Gets status if we already tried to initialize the encryption app diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 88eacc6f13..df5de55886 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -167,6 +167,9 @@ class Stream { } else { $this->meta = stream_get_meta_data($this->handle); + // sometimes fopen changes the mode, e.g. for a url "r" convert to "r+" + // but we need to remember the original access type + $this->meta['mode'] = $mode; } @@ -542,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 @@ -565,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); } - return fclose($this->handle); + $result = fclose($this->handle); + + if ($result === false) { + \OCP\Util::writeLog('Encryption library', 'Could not close stream, file could be corrupted', \OCP\Util::FATAL); + } + + return $result; + } } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index ec06bd52f5..6372ab31b6 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -135,7 +135,6 @@ class Util { // Set directories to check / create $setUpDirs = array( $this->userDir, - $this->userFilesDir, $this->publicKeyDir, $this->encryptionDir, $this->keyfilesPath, @@ -433,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 @@ -967,33 +969,6 @@ class Util { } - /** - * @brief get path of a file. - * @param int $fileId id of the file - * @return string path of the file - */ - public static function fileIdToPath($fileId) { - - $sql = 'SELECT `path` FROM `*PREFIX*filecache` WHERE `fileid` = ?'; - - $query = \OCP\DB::prepare($sql); - - $result = $query->execute(array($fileId)); - - $path = false; - if (\OCP\DB::isError($result)) { - \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); - } else { - $row = $result->fetchRow(); - if ($row) { - $path = substr($row['path'], strlen('files')); - } - } - - return $path; - - } - /** * @brief Filter an array of UIDs to return only ones ready for sharing * @param array $unfilteredUsers users to be checked for sharing readiness @@ -1125,8 +1100,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(); @@ -1145,12 +1121,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; } @@ -1166,11 +1144,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(); @@ -1398,7 +1371,7 @@ class Util { * @param string $dir relative to the users files folder * @return array with list of files relative to the users files folder */ - public function getAllFiles($dir) { + public function getAllFiles($dir, $mountPoint = '') { $result = array(); $dirList = array($dir); @@ -1408,11 +1381,13 @@ class Util { $this->userFilesDir . '/' . $dir)); foreach ($content as $c) { - $usersPath = isset($c['usersPath']) ? $c['usersPath'] : $c['path']; + // getDirectoryContent() returns the paths relative to the mount points, so we need + // to re-construct the complete path + $path = ($mountPoint !== '') ? $mountPoint . '/' . $c['path'] : $c['path']; if ($c['type'] === 'dir') { - $dirList[] = substr($usersPath, strlen("files")); + $dirList[] = substr($path, strlen("files")); } else { - $result[] = substr($usersPath, strlen("files")); + $result[] = substr($path, strlen("files")); } } @@ -1421,54 +1396,6 @@ class Util { return $result; } - /** - * @brief get shares parent. - * @param int $id of the current share - * @return array of the parent - */ - public static function getShareParent($id) { - - $sql = 'SELECT `file_target`, `item_type` FROM `*PREFIX*share` WHERE `id` = ?'; - - $query = \OCP\DB::prepare($sql); - - $result = $query->execute(array($id)); - - $row = array(); - if (\OCP\DB::isError($result)) { - \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); - } else { - $row = $result->fetchRow(); - } - - return $row; - - } - - /** - * @brief get shares parent. - * @param int $id of the current share - * @return array of the parent - */ - public static function getParentFromShare($id) { - - $sql = 'SELECT `parent` FROM `*PREFIX*share` WHERE `id` = ?'; - - $query = \OCP\DB::prepare($sql); - - $result = $query->execute(array($id)); - - $row = array(); - if (\OCP\DB::isError($result)) { - \OCP\Util::writeLog('Encryption library', \OC_DB::getErrorMessage($result), \OCP\Util::ERROR); - } else { - $row = $result->fetchRow(); - } - - return $row; - - } - /** * @brief get owner of the shared files. * @param $id @@ -1710,23 +1637,6 @@ class Util { $this->recoverAllFiles('/', $privateKey); } - /** - * Get the path including the storage mount point - * @param int $id - * @return string the path including the mount point like AmazonS3/folder/file.txt - */ - public function getPathWithMountPoint($id) { - list($storage, $internalPath) = \OC\Files\Cache\Cache::getById($id); - $mount = \OC\Files\Filesystem::getMountByStorageId($storage); - $mountPoint = $mount[0]->getMountPoint(); - $path = \OC\Files\Filesystem::normalizePath($mountPoint . '/' . $internalPath); - - // reformat the path to be relative e.g. /user/files/folder becomes /folder/ - $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); - - return $relativePath; - } - /** * @brief check if the file is stored on a system wide mount point * @param $path relative to /data/user with leading '/' @@ -1772,4 +1682,12 @@ class Util { return $session; } + /* + * @brief remove encryption related keys from the session + */ + public function closeEncryptionSession() { + $session = new \OCA\Encryption\Session($this->view); + $session->closeSession(); + } + } diff --git a/apps/files_encryption/templates/settings-admin.php b/apps/files_encryption/templates/settings-admin.php index 231a68b6a5..cf676c445c 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 1b4239d82c..8139ece195 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( "Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" ) ); ?> -
- /> - t( "Enabled" ) ); ?> -
+ 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( "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/hooks.php b/apps/files_encryption/tests/hooks.php index 7d926caea1..047084ca2c 100644 --- a/apps/files_encryption/tests/hooks.php +++ b/apps/files_encryption/tests/hooks.php @@ -47,6 +47,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { public $rootView; // view on /data/user public $data; public $filename; + public $folder; public static function setUpBeforeClass() { // reset backend @@ -89,6 +90,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { // init short data $this->data = 'hats'; $this->filename = 'enc_hooks_tests-' . uniqid() . '.txt'; + $this->folder = 'enc_hooks_tests_folder-' . uniqid(); } @@ -217,18 +219,20 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2); \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2); - // user2 has a local file with the same name + // user2 update the shared file $this->user2View->file_put_contents($this->filename, $this->data); - // check if all keys are generated - $this->assertTrue($this->rootView->file_exists( + // keys should be stored at user1s dir, not in user2s + $this->assertFalse($this->rootView->file_exists( self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/' . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); - $this->assertTrue($this->rootView->file_exists( + $this->assertFalse($this->rootView->file_exists( self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key')); // delete the Shared file from user1 in data/user2/files/Shared - $this->user2View->unlink('/Shared/' . $this->filename); + $result = $this->user2View->unlink($this->filename); + + $this->assertTrue($result); // now keys from user1s home should be gone $this->assertFalse($this->rootView->file_exists( @@ -240,26 +244,12 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { $this->assertFalse($this->rootView->file_exists( self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key')); - // but user2 keys should still exist - $this->assertTrue($this->rootView->file_exists( - self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/' - . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey')); - $this->assertTrue($this->rootView->file_exists( - self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key')); - // cleanup - $this->user2View->unlink($this->filename); - \Test_Encryption_Util::logoutHelper(); \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1); \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1); - // unshare the file - \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2); - - $this->user1View->unlink($this->filename); - if ($stateFilesTrashbin) { OC_App::enable('files_trashbin'); } @@ -268,4 +258,57 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { } } + /** + * @brief test rename operation + */ + function testRenameHook() { + + // save file with content + $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data); + + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile)); + + // check if keys exists + $this->assertTrue($this->rootView->file_exists( + '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' + . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + + $this->assertTrue($this->rootView->file_exists( + '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' + . $this->filename . '.key')); + + // make subfolder + $this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); + + $this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder)); + + // move the file out of the shared folder + $root = $this->rootView->getRoot(); + $this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/'); + $this->rootView->rename($this->filename, '/' . $this->folder . '/' . $this->filename); + $this->rootView->chroot($root); + + $this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename)); + $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->filename)); + + // keys should be renamed too + $this->assertFalse($this->rootView->file_exists( + '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' + . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + $this->assertFalse($this->rootView->file_exists( + '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' + . $this->filename . '.key')); + + $this->assertTrue($this->rootView->file_exists( + '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' + . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + $this->assertTrue($this->rootView->file_exists( + '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/' + . $this->filename . '.key')); + + // cleanup + $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); + } + } diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index 51cc0b795e..647ee955eb 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -112,4 +112,24 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase { } + function testPostFileSizeWithDirectory() { + + $this->view->file_put_contents($this->filename, $this->data); + + \OC_FileProxy::$enabled = false; + + // get root size, must match the file's unencrypted size + $unencryptedSize = $this->view->filesize(''); + + \OC_FileProxy::$enabled = true; + + $encryptedSize = $this->view->filesize(''); + + $this->assertTrue($encryptedSize !== $unencryptedSize); + + // cleanup + $this->view->unlink($this->filename); + + } + } diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 46a21dd55c..512671c576 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() { @@ -127,6 +127,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { \OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4); } + /** * @medium * @param bool $withTeardown @@ -174,7 +175,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get file contents $retrievedCryptedFile = $this->view->file_get_contents( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename); + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename); // check if data is the same as we previously written $this->assertEquals($this->dataShort, $retrievedCryptedFile); @@ -212,14 +213,14 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { function testReShareFile($withTeardown = true) { $this->testShareFile(false); - // login as user1 + // login as user2 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); // get the file info $fileInfo = $this->view->getFileInfo( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename); + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename); - // share the file with user2 + // share the file with user3 \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, OCP\PERMISSION_ALL); // login as admin @@ -235,7 +236,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get file contents $retrievedCryptedFile = $this->view->file_get_contents( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared/' . $this->filename); + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/' . $this->filename); // check if data is the same as previously written $this->assertEquals($this->dataShort, $retrievedCryptedFile); @@ -332,7 +333,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get file contents $retrievedCryptedFile = $this->view->file_get_contents( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared' . $this->folder1 + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename); // check if data is the same @@ -375,7 +376,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { function testReShareFolder($withTeardown = true) { $fileInfoFolder1 = $this->testShareFolder(false); - // login as user1 + // login as user2 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); // disable encryption proxy to prevent recursive calls @@ -384,7 +385,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get the file info from previous created folder $fileInfoSubFolder = $this->view->getFileInfo( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared' . $this->folder1 + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->subfolder); // check if we have a valid file info @@ -393,24 +394,24 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // re-enable the file proxy \OC_FileProxy::$enabled = $proxyStatus; - // share the file with user2 + // share the file with user3 \OCP\Share::shareItem('folder', $fileInfoSubFolder['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3, OCP\PERMISSION_ALL); // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); - // check if share key for user2 exists + // check if share key for user3 exists $this->assertTrue($this->view->file_exists( '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys' . $this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey')); - // login as user2 + // login as user3 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3); // get file contents $retrievedCryptedFile = $this->view->file_get_contents( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared' . $this->subfolder + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/' . $this->subfolder . $this->subsubfolder . '/' . $this->filename); // check if data is the same @@ -418,7 +419,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get the file info $fileInfo = $this->view->getFileInfo( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared' . $this->subfolder + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/' . $this->subfolder . $this->subsubfolder . '/' . $this->filename); // check if we have fileInfos @@ -441,7 +442,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get file contents $retrievedCryptedFile = $this->view->file_get_contents( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '/files/Shared/' . $this->filename); + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '/files/' . $this->filename); // check if data is the same $this->assertEquals($this->dataShort, $retrievedCryptedFile); @@ -498,6 +499,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { } } + function testPublicShareFile() { // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); @@ -622,7 +624,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // get file contents $retrievedCryptedFile = $this->view->file_get_contents( - '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/Shared/' . $this->filename); + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '/files/' . $this->filename); // check if data is the same as we previously written $this->assertEquals($this->dataShort, $retrievedCryptedFile); @@ -674,6 +676,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // enable recovery for admin $this->assertTrue($util->setRecoveryForUser(1)); + $util->addRecoveryKeys(); // create folder structure $this->view->mkdir('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1); @@ -864,6 +867,13 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { \OCA\Encryption\Helper::adminDisableRecovery('test123'); $this->assertEquals(0, \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled')); + + //clean up, reset passwords + \OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test123'); + $params = array('uid' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, + 'password' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, + 'recoveryPassword' => 'test123'); + \OCA\Encryption\Hooks::setPassphrase($params); } /** @@ -947,4 +957,63 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { $this->view->chroot('/'); } + + /** + * @brief test moving a shared file out of the Shared folder + */ + function testRename() { + + // login as admin + \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); + + // save file with content + $cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort); + + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile)); + + // get the file info from previous created file + $fileInfo = $this->view->getFileInfo( + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); + + // check if we have a valid file info + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); + + // share the file + \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL); + + // check if share key for user2 exists + $this->assertTrue($this->view->file_exists( + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/' + . $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey')); + + + // login as user2 + \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); + + $this->assertTrue($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename)); + + // get file contents + $retrievedCryptedFile = $this->view->file_get_contents( + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename); + + // check if data is the same as we previously written + $this->assertEquals($this->dataShort, $retrievedCryptedFile); + + // move the file to a subfolder + $this->view->rename('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename, + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->filename); + + // check if we can read the moved file + $retrievedRenamedFile = $this->view->file_get_contents( + '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1 . $this->filename); + + // check if data is the same as we previously written + $this->assertEquals($this->dataShort, $retrievedRenamedFile); + + // cleanup + \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); + $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); + } + } diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index f70e30c4d7..88ded7ec40 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -344,15 +344,17 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { // check if mtime and etags unchanged $this->assertEquals($fileInfoEncrypted['mtime'], $fileInfoUnencrypted['mtime']); - $this->assertEquals($fileInfoEncrypted['etag'], $fileInfoUnencrypted['etag']); + $this->assertSame($fileInfoEncrypted['etag'], $fileInfoUnencrypted['etag']); $this->view->unlink($this->userId . '/files/' . $filename); } - function testDecryptAll() { $filename = "/decryptAll" . uniqid() . ".txt"; + $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/'); + $userdir = $datadir . '/' . $this->userId . '/files/'; + $util = new Encryption\Util($this->view, $this->userId); $this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort); @@ -362,25 +364,62 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $this->assertTrue($fileInfoEncrypted instanceof \OC\Files\FileInfo); $this->assertEquals($fileInfoEncrypted['encrypted'], 1); - // decrypt all encrypted files - $result = $util->decryptAll('/' . $this->userId . '/' . 'files'); + $encContent = file_get_contents($userdir . $filename); - $this->assertTrue($result); + \OC_App::disable('files_encryption'); + + $user = \OCP\User::getUser(); + $this->logoutHelper(); + $this->loginHelper($user, false, false, false); + + $content = file_get_contents($userdir . $filename); + + //content should be encrypted + $this->assertSame($encContent, $content); + + // now we load the encryption app again + OC_App::loadApp('files_encryption'); + + // init encryption app + $params = array('uid' => \OCP\User::getUser(), + 'password' => \OCP\User::getUser()); + + $view = new OC_FilesystemView('/'); + $util = new \OCA\Encryption\Util($view, \OCP\User::getUser()); + + $result = $util->initEncryption($params); + + $this->assertTrue($result instanceof \OCA\Encryption\Session); + + $successful = $util->decryptAll(); + + $this->assertTrue($successful); + + $this->logoutHelper(); + $this->loginHelper($user, false, false, false); + + // file should be unencrypted and fileInfo should contain the correct values + $content = file_get_contents($userdir . $filename); + + // now we should get the plain data + $this->assertSame($this->dataShort, $content); $fileInfoUnencrypted = $this->view->getFileInfo($this->userId . '/files/' . $filename); - $this->assertTrue($fileInfoUnencrypted instanceof \OC\Files\FileInfo); // check if mtime and etags unchanged $this->assertEquals($fileInfoEncrypted['mtime'], $fileInfoUnencrypted['mtime']); - $this->assertEquals($fileInfoEncrypted['etag'], $fileInfoUnencrypted['etag']); + $this->assertSame($fileInfoEncrypted['etag'], $fileInfoUnencrypted['etag']); // file should no longer be encrypted $this->assertEquals(0, $fileInfoUnencrypted['encrypted']); + // cleanup $this->view->unlink($this->userId . '/files/' . $filename); + OC_App::enable('files_encryption'); } + function testDescryptAllWithBrokenFiles() { $file1 = "/decryptAll1" . uniqid() . ".txt"; @@ -508,9 +547,13 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { * @param bool $create * @param bool $password */ - public static function loginHelper($user, $create = false, $password = false) { + public static function loginHelper($user, $create = false, $password = false, $loadEncryption = true) { if ($create) { - \OC_User::createUser($user, $user); + try { + \OC_User::createUser($user, $user); + } catch(\Exception $e) { // catch username is already being used from previous aborted runs + + } } if ($password === false) { @@ -520,12 +563,14 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { \OC_Util::tearDownFS(); \OC_User::setUserId(''); \OC\Files\Filesystem::tearDown(); - \OC_Util::setupFS($user); \OC_User::setUserId($user); + \OC_Util::setupFS($user); - $params['uid'] = $user; - $params['password'] = $password; - OCA\Encryption\Hooks::login($params); + if ($loadEncryption) { + $params['uid'] = $user; + $params['password'] = $password; + OCA\Encryption\Hooks::login($params); + } } public static function logoutHelper() { diff --git a/apps/files_encryption/tests/webdav.php b/apps/files_encryption/tests/webdav.php index 8e8b9c53ce..1fe4c13d59 100755 --- a/apps/files_encryption/tests/webdav.php +++ b/apps/files_encryption/tests/webdav.php @@ -33,6 +33,7 @@ use OCA\Encryption; /** * Class Test_Encryption_Webdav + * * @brief this class provide basic webdav tests for PUT,GET and DELETE */ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { @@ -48,6 +49,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { public $dataShort; public $stateFilesTrashbin; + private static $storage; + public static function setUpBeforeClass() { // reset backend \OC_User::clearBackends(); @@ -65,6 +68,8 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { // create test user \Test_Encryption_Util::loginHelper(\Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1, true); + + self::$storage = new \OC\Files\Storage\Temporary(array()); } function setUp() { @@ -96,8 +101,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { // reset app files_trashbin if ($this->stateFilesTrashbin) { OC_App::enable('files_trashbin'); - } - else { + } else { OC_App::disable('files_trashbin'); } } @@ -153,7 +157,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { $this->assertTrue(Encryption\Crypt::isCatfileContent($encryptedContent)); // get decrypted file contents - $decrypt = file_get_contents('crypt:///' . $this->userId . '/files'. $filename); + $decrypt = file_get_contents('crypt:///' . $this->userId . '/files' . $filename); // check if file content match with the written content $this->assertEquals($this->dataShort, $decrypt); @@ -225,7 +229,12 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { $requestBackend = new OC_Connector_Sabre_Request(); // Create ownCloud Dir - $publicDir = new OC_Connector_Sabre_Directory(''); + $root = '/' . $this->userId . '/files'; + \OC\Files\Filesystem::mount(self::$storage, array(), $root); + $view = new \OC\Files\View($root); + $publicDir = new OC_Connector_Sabre_Directory($view, $view->getFileInfo('')); + $objectTree = new \OC\Connector\Sabre\ObjectTree(); + $objectTree->init($publicDir, $view); // Fire up server $server = new Sabre_DAV_Server($publicDir); @@ -236,8 +245,9 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { $server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend, 'ownCloud')); $server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend)); $server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload - $server->addPlugin(new OC_Connector_Sabre_QuotaPlugin()); + $server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view)); $server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin()); + $server->debugExceptions = true; // And off we go! if ($body) { diff --git a/apps/files_external/3rdparty/irodsphp/LICENSE.txt b/apps/files_external/3rdparty/irodsphp/LICENSE.txt deleted file mode 100644 index caca18c59b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -iRODS license terms and copyright info from the irods site at: https://www.irods.org/index.php/License - -License -iRODS Copyright and Licensing - -iRODS is open source software released under a BSD License, see license text in "iRODS License Terms and Conditions" below. -The BSD license has been described in very general terms as allowing you to do whatever you want to with the software and -source code as long as you acknowledge who wrote it and that, as with any open source software, there is no warranty and you're using the code "as is." -In the spirit of collaborative open source software, the iRODS community encourages you to communicate with us, letting us know what features you like, -features that would be useful, problems, bugs, suggestions, etc., and to perhaps contribute source code. -The iRODS community has formed the Data Intensive Cyberinfrastructure Foundation, a 501(c)(3) nonprofit corporation established to serve - as the home of the iRODS open source community over the long term. If you choose to contribute new code, you'll receive full acknowledgment. All you do is complete the Contributor's Agreement, under which you retain copyright ownership - in your code but give a free license to the iRODS nonprofit foundation, allowing your code to be integrated into iRODS and in turn released under the BSD license. -Note: The above text is an educational overview of iRODS open source licensing, and not intended as legal advice nor is it part of the iRODS license agreement, which is below. As always, for legal advice consult an attorney. - -iRODS License Terms and Conditions Notice - -Copyright (c) 2005-2011, Regents of the University of California, the University of North Carolina, and the Data Intensive Cyberinfrastructure Foundation -All rights reserved. -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -Neither the name of the University of California, San Diego (UCSD) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/doc_config.ini b/apps/files_external/3rdparty/irodsphp/prods/doc_config.ini deleted file mode 100644 index f72b4a230d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/doc_config.ini +++ /dev/null @@ -1,87 +0,0 @@ -;; phpDocumentor demonstration parse configuration file -;; -;; RUN THIS FILE FROM THE INSTALL DIRECTORY -;; CHANGE HERE: - -;; where should the documentation be written? -;; legal values: a legal path -;target = /home/CelloG/output -target = ./doc - - -;; DONT CHANGE BELOW HERE -;; -;; This file is designed to cut down on repetitive typing on the command-line or web interface -;; You can copy this file to create a number of configuration files that can be used with the -;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web -;; interface will automatically generate a list of .ini files that can be used. -;; -;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini -;; -;; Copyright 2002, Greg Beaver -;; -;; WARNING: do not change the - -[Parse Data] -;; title of all the documentation -;; legal values: any string -title = PRODS (iRODS PHP Client API) Documentation - -;; parse files that start with a . like .bash_profile -;; legal values: true, false -hidden = false - -;; show elements marked @access private in documentation by setting this to on -;; legal values: on, off -parseprivate = off - -;; parse with javadoc-like description (first sentence is always the short description) -;; legal values: on, off -javadocdesc = on - -;target=/dev/null - -;; add any custom @tags separated by commas here -;; legal values: any legal tagname separated by commas. -;customtags = mytag1,mytag2 - -;; what is the main package? -;; legal values: alphanumeric string plus - and _ -defaultpackagename = Prods - -;; output any parsing information? set to on for cron jobs -;; legal values: on -;quiet = on - -;; limit output to the specified packages, even if others are parsed -;; legal values: package names separated by commas -;packageoutput = package1,package2 - -;; comma-separated list of files to parse -;; legal values: paths separated by commas -;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory - -;; comma-separated list of directories to parse -;; legal values: directory paths separated by commas -;directory = /path1,/path2,.,..,subdirectory -;directory = /home/jeichorn/cvs/pear -;directory = /you-MUST/change-me/to-fit/your-environment -;directory = . - -directory = ./src,./tutorials - -;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore -;; legal values: any wildcard strings separated by commas -;; remember, this pathing is RELATIVE to the top-most directory in your "directory" value -;ignore = path/to/ignore*,*list.php,myfile.php,subdirectory/ -ignore = templates_c/,*HTML/default/*,spec/,*.inc.php,packet/,set*.php,ProdsStreamer.class.php,RODSMessage.class.php,RODSConn.class.php,RODSKeyValPair.class.php,RODSConnManager.class.php - -;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format -;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib -;; HTML:frames:phpedit,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de -;; HTML:Smarty:default,HTML:Smarty:PHP,PDF:default:default,CHM:default:default,XML:DocBook:default -output=HTML:Smarty:PHP - -;; turn this option on if you want highlighted source code for every file -;; legal values: on/off -sourcecode = on diff --git a/apps/files_external/3rdparty/irodsphp/prods/release_notes.txt b/apps/files_external/3rdparty/irodsphp/prods/release_notes.txt deleted file mode 100644 index 7e1b0549cf..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/release_notes.txt +++ /dev/null @@ -1,34 +0,0 @@ - -*'''Project''': PHP Prods API for iRODS -*'''Date''': 06/04/2013 -*'''Release Version''': 3.3.0-beta1 -*'''git tag''': 3.3.0-beta1 - -==News== - -PHP API for iRODS - -This alpha is a merge of community supported additions for PAM and tickets - - -GForge for iDrop-swing is at: [[https://code.renci.org/gf/project/irodsphp/]] - -==Requirements== - -Note that the following bug and feature requests are logged in GForge with related commit information [[https://code.renci.org/gf/project/irodsphp/tracker/]] - -==Features== - -*[#1280] Add PAM support to PHP - -*[#1122] Add Ticket support to PHP - -==Bug Fixes== - - - -==Outstanding Issues== - -Please consult [[https://code.renci.org/gf/project/irodsphp/tracker/]] - -for the latest open bugs and Jargon feature requests diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/LICENSE.txt b/apps/files_external/3rdparty/irodsphp/prods/src/LICENSE.txt deleted file mode 100644 index caca18c59b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -iRODS license terms and copyright info from the irods site at: https://www.irods.org/index.php/License - -License -iRODS Copyright and Licensing - -iRODS is open source software released under a BSD License, see license text in "iRODS License Terms and Conditions" below. -The BSD license has been described in very general terms as allowing you to do whatever you want to with the software and -source code as long as you acknowledge who wrote it and that, as with any open source software, there is no warranty and you're using the code "as is." -In the spirit of collaborative open source software, the iRODS community encourages you to communicate with us, letting us know what features you like, -features that would be useful, problems, bugs, suggestions, etc., and to perhaps contribute source code. -The iRODS community has formed the Data Intensive Cyberinfrastructure Foundation, a 501(c)(3) nonprofit corporation established to serve - as the home of the iRODS open source community over the long term. If you choose to contribute new code, you'll receive full acknowledgment. All you do is complete the Contributor's Agreement, under which you retain copyright ownership - in your code but give a free license to the iRODS nonprofit foundation, allowing your code to be integrated into iRODS and in turn released under the BSD license. -Note: The above text is an educational overview of iRODS open source licensing, and not intended as legal advice nor is it part of the iRODS license agreement, which is below. As always, for legal advice consult an attorney. - -iRODS License Terms and Conditions Notice - -Copyright (c) 2005-2011, Regents of the University of California, the University of North Carolina, and the Data Intensive Cyberinfrastructure Foundation -All rights reserved. -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -Neither the name of the University of California, San Diego (UCSD) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/Prods.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/Prods.inc.php deleted file mode 100644 index 7e0fafdad8..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/Prods.inc.php +++ /dev/null @@ -1,3 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ - -require_once("autoload.inc.php"); - -class ProdsDir extends ProdsPath -{ - /** - * @var RODSDirStats - */ - public $stats; - - private $child_dirs; - private $child_files; - private $all_children; - private $position; - - /** - * Default Constructor. - * - * @param RODSAccount account iRODS account used for connection - * @param string $path_str the path of this dir - * @param boolean $verify whether verify if the path exsits - * @param RODSDirStats $stats if the stats for this dir is already known, initilize it here. - * @return a new ProdsDir - */ - public function __construct(RODSAccount &$account, $path_str, $verify = false, - RODSDirStats $stats = NULL) - { - $this->position = 0; - $this->stats = $stats; - parent::__construct($account, $path_str); - if ($verify === true) { - if ($this->exists() === false) { - throw new RODSException("Directory '$this' does not exist", - 'PERR_PATH_DOES_NOT_EXISTS'); - } - } - } - - - /** - * Create a ProdsDir object from URI string. - * @param string $path the URI Sting - * @param boolean $verify whether verify if the path exsits - * @return a new ProdsDir - */ - public static function fromURI($path, $verify=false) - { - if (0!=strncmp($path,"rods://",7)) - $path="rods://".$path; - $url=parse_url($path); - - $host=isset($url['host'])?$url['host']:''; - $port=isset($url['port'])?$url['port']:''; - - $user=''; - $zone=''; - $authtype='irods'; - if (isset($url['user'])) - { - if (strstr($url['user'],".")!==false) { - $user_array=@explode(".",$url['user']); - if (count($user_array)===3) { - $user=$user_array[0]; - $zone=$user_array[1]; - $authtype=$user_array[2]; - } - else { - $user=$user_array[0]; - $zone=$user_array[1]; - } - } - else - $user=$url['user']; - } - - $pass=isset($url['pass'])?$url['pass']:''; - - $account=new RODSAccount($host, $port, $user, $pass, $zone, '', $authtype); - - $path_str=isset($url['path'])?$url['path']:''; - - // treat query and fragment as part of name - if (isset($url['query'])&&(strlen($url['query'])>0)) - $path_str=$path_str.'?'.$url['query']; - if (isset($url['fragment'])&&(strlen($url['fragment'])>0)) - $path_str=$path_str.'#'.$url['fragment']; - - if (empty($path_str)) - $path_str='/'; - - return (new ProdsDir($account,$path_str,$verify)); - } - - /** - * Verify if this dir exist with server. This function shouldn't be called directly, use {@link exists} - */ - //protected function verify() - protected function verify($get_cb=array('RODSConnManager','getConn'), - $rel_cb=array('RODSConnManager', 'releaseConn')) - { - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $this->path_exists= $conn -> dirExists ($this->path_str); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - } - - /** - * get next file or directory from the directory, where the internal iterator points to. - * @return next file or directory from the directory. The file always come first and dir comes later. return false on failure - */ - public function getNextChild() - { - if (!$this->all_children) - $this->all_children=$this->getAllChildren(); - if (($this->position>=count($this->all_children))||($this->position<0)) - return false; - $names=array_keys($this->all_children); - $ret_val=$this->all_children[$names[$this->position]]; - $this->position++; - return $ret_val; - } - - - /** - * Get children files of this dir. - * - * @param array $orderby An associated array specifying how to sort the result by attributes. See details in method {@link findFiles}; - * @param int $startingInx starting index of all files. default is 0. - * @param int $maxresults max results returned. if negative, it returns all rows. default is -1 - * @param int &$total_num_rows number of all results - * @param boolean $logical_file whether to return only logical files, if false, it returns all replica with resource name, if true, it returns only 1 logical file, with num_replica available in the stats. default is false. - * @return an array of ProdsFile - */ - public function getChildFiles(array $orderby=array(), $startingInx=0, - $maxresults=-1, &$total_num_rows=-1, $logicalFile=false) - { - $terms=array("descendantOnly"=>true,"recursive"=>false, 'logicalFile'=>$logicalFile); - return $this->findFiles($terms,$total_num_rows,$startingInx,$maxresults,$orderby); - } - - /** - * Resets the directory stream to the beginning of the directory. - */ - public function rewind() - { - $this->position = 0; - } - - - /** - * @return all children (files and dirs) of current dir - */ - public function getAllChildren() - { - $this->all_children = array(); - $this->all_children = array_merge($this->all_children, - $this->getChildFiles()); - $this->all_children = array_merge($this->all_children, - $this->getChildDirs()); - - return $this->all_children; - } - - /** - * Get children directories of this dir. - * @param $orderby An associated array specifying how to sort the result by attributes. See details in method {@link findDirs}; - * Note that if the current dir is root '/', it will not return '/' as its child, unlike iCommand's current behavior. - * @return an array of ProdsDir - */ - public function getChildDirs(array $orderby = array(), $startingInx = 0, - $maxresults = -1, &$total_num_rows = -1) - { - $terms = array("descendantOnly" => true, "recursive" => false); - return $this->findDirs($terms, $total_num_rows, $startingInx, $maxresults, $orderby); - } - - /** - * Make a new directory under this directory - * @param string $name full path of the new dir to be made on server - * @return ProdsDir the new directory just created (or already exists) - */ - // public function mkdir($name) - public function mkdir($name, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->mkdir($this->path_str . "/$name"); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - return (new ProdsDir($this->account, $this->path_str . "/$name")); - } - - /** - * remove this directory - * @param boolean $recursive whether recursively delete all child files and child directories recursively. - * @param boolean $force whether force delete the file/dir. If force delete, all files will be wiped physically. Else, they are moved to trash derectory. - * @param array $additional_flags An array of keyval pairs (array) reprenting additional flags passed to the server/client message. Each keyval pair is an array with first element repsenting the key, and second element representing the value (default to ''). Supported keys are: - * - 'irodsRmTrash' - whether this rm is a rmtrash operation - * - 'irodsAdminRmTrash' - whether this rm is a rmtrash operation done by admin user - * @param mixed $status_update_func It can be an string or array that represents the status update function (see http://us.php.net/manual/en/language.pseudo-types.php#language.types.callback), which can update status based on the server status update. Leave it blank or 'null' if there is no need to update the status. The function will be called with an assossive arry as parameter, supported fields are: - * - 'filesCnt' - finished number of files from previous update (normally 10 but not the last update) - * - 'lastObjPath' - last object that was processed. - * If this function returns 1, progress will be stopped. - */ - // public function rmdir($recursive=true,$force=false, $additional_flags=array(), - // $status_update_func=null) - public function rmdir($recursive = true, $force = false, $additional_flags = array(), - $status_update_func = null, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->rmdir($this->path_str, $recursive, $force, $additional_flags, - $status_update_func); - // RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - } - - /** - * get the dir stats - * @param boolean $force_reload If stats already present in the object, and this flag is true, a force reload will be done. - * @return RODSDirStats the stats object, note that if this object will not refresh unless $force_reload flag is used. - */ - // public function getStats($force_reload=false) - public function getStats($force_reload = false, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if (($force_reload === false) && ($this->stats)) - return $this->stats; - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $stats = $conn->getDirStats($this->path_str); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - - if ($stats === false) $this->stats = NULL; - else $this->stats = $stats; - return $this->stats; - } - - public function getACL() - { - - $collection = $this->path_str; - - $connLocal = RODSConnManager::getConn($this->account); - $que_result_coll = $connLocal->genQuery( - array("COL_COLL_INHERITANCE", "COL_COLL_NAME", "COL_COLL_OWNER_NAME", "COL_COLL_ID"), - array(new RODSQueryCondition("COL_COLL_NAME", $collection))); - - $users['COL_COLL_INHERITANCE'] = (int)($que_result_coll['COL_COLL_INHERITANCE'][0]); - - $que_result_users = $connLocal->genQuery( - array("COL_DATA_ACCESS_NAME", "COL_DATA_ACCESS_USER_ID"), - array(new RODSQueryCondition("COL_DATA_ACCESS_DATA_ID", $que_result_coll['COL_COLL_ID'][0]))); - - for($i=0; $igenQuery( - array("COL_USER_NAME", "COL_USER_ZONE"), - array(new RODSQueryCondition("COL_USER_ID", $que_result_users["COL_DATA_ACCESS_USER_ID"][$i]))); - - $users['COL_USERS'][] = (object) array( - "COL_USER_NAME" => $que_result_user_info['COL_USER_NAME'][0], - "COL_USER_ZONE" => $que_result_user_info['COL_USER_ZONE'][0], - "COL_DATA_ACCESS_NAME" => $que_result_users['COL_DATA_ACCESS_NAME'][$i] - ); - } - - RODSConnManager::releaseConn($connLocal); - return $users; - - - } - - /** - * get the dir statistics, such as total number of files under this dir - * @param string $fld Name of the statistics, supported values are: - * - num_dirs number of directories - * - num_files number of files - * @param boolean $recursive wheather recursively through the sub collections, default is true. - * @return result, an integer value, assosiated with the query. - */ - //public function queryStatistics($fld, $recursive=true) - public function queryStatistics($fld, $recursive = true, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - $condition = new RODSGenQueConds(); - $select = new RODSGenQueSelFlds(); - $ret_data_index = ''; - switch ($fld) { - case 'num_dirs' : - $select->add('COL_COLL_ID', 'count'); - $ret_data_index = 'COL_COLL_ID'; - if ($recursive === true) - $condition->add('COL_COLL_NAME', 'like', $this->path_str . '/%'); - else - $condition->add('COL_COLL_PARENT_NAME', '=', $this->path_str); - break; - case 'num_files' : - $select->add('COL_D_DATA_ID', 'count'); - $ret_data_index = 'COL_D_DATA_ID'; - if ($recursive === true) - $condition->add('COL_COLL_NAME', 'like', $this->path_str . '/%', - array(array('op' => '=', 'val' => $this->path_str))); - else - $condition->add('COL_COLL_NAME', '=', $this->path_str); - break; - default : - throw new RODSException("Query field '$fld' not supported!", - 'PERR_USER_INPUT_ERROR'); - } - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $results = $conn->query($select, $condition); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - $result_values = $results->getValues(); - - if (isset($result_values[$ret_data_index][0])) - return intval($result_values[$ret_data_index][0]); - else { - throw new RODSException("Query did not get value back with expected " . - "index: $ret_data_index!", 'GENERAL_PRODS_ERR'); - } - } - - /** - * query metadata, and find matching files. - * @param array $terms an assositive array of search conditions, supported ones are: - * - 'name' (string) - partial name of the target (file or dir) - * - 'descendantOnly' (boolean) - whether to search among this directory's decendents. default is false. - * - 'recursive' (boolean) - whether to search recursively, among all decendents and their children. default is false. This option only works when 'descendantOnly' is true - * - 'logicalFile' (boolean) - whether to return logical file, instead of all replicas for each file. if true, the resource name for each file will be null, instead, num_replicas will be provided. default is false. - * - 'smtime' (int) - start last-modified-time in unix timestamp. The specified time is included in query, in other words the search can be thought was "mtime >= specified time" - * - 'emtime' (int) - end last-modified-time in unix timestamp. The specified time is not included in query, in other words the search can be thought was "mtime < specified time" - * - 'owner' (string) - owner name of the file - * - 'rescname' (string) - resource name of the file - * - 'metadata' (array of RODSMeta) - array of metadata. - * @param int &$total_count This value (passed by reference) returns the total potential count of search results - * @param int $start starting index of search results. - * @param int $limit up to how many results to be returned. If negative, give all results back. - * @param array $sort_flds associative array with following keys: - * - 'name' - name of the file or dir - * - 'size' - size of the file - * - 'mtime' - last modified time - * - 'ctime' - creation time - * - 'owner' - owner of the file - * - 'typename' - file/data type - * - 'dirname' - directory/collection name for the file - * The results are sorted by specified array keys. - * The possible array value must be boolean: true stands for 'asc' and false stands for 'desc', default is 'asc' - * @return array of ProdsPath objects (ProdsFile or ProdsDir). - */ - //public function findFiles(array $terms, &$total_count, $start=0, $limit=-1, array $sort_flds=array()) - public function findFiles(array $terms, &$total_count, $start = 0, $limit = -1, - array $sort_flds = array(), - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - $flds = array("COL_DATA_NAME" => NULL, "COL_D_DATA_ID" => NULL, - "COL_DATA_TYPE_NAME" => NULL, "COL_D_RESC_NAME" => NULL, - "COL_DATA_SIZE" => NULL, "COL_D_OWNER_NAME" => NULL, "COL_D_OWNER_ZONE" => NULL, - "COL_D_CREATE_TIME" => NULL, "COL_D_MODIFY_TIME" => NULL, - "COL_COLL_NAME" => NULL, "COL_D_COMMENTS" => NULL); - - foreach ($sort_flds as $sort_fld_key => $sort_fld_val) { - switch ($sort_fld_key) { - case 'name': - if ($sort_fld_val === false) - $flds['COL_DATA_NAME'] = 'order_by_desc'; - else - $flds['COL_DATA_NAME'] = 'order_by_asc'; - break; - - case 'size': - if ($sort_fld_val === false) - $flds['COL_DATA_SIZE'] = 'order_by_desc'; - else - $flds['COL_DATA_SIZE'] = 'order_by_asc'; - break; - - case 'mtime': - if ($sort_fld_val === false) - $flds['COL_D_MODIFY_TIME'] = 'order_by_desc'; - else - $flds['COL_D_MODIFY_TIME'] = 'order_by_asc'; - break; - - case 'ctime': - if ($sort_fld_val === false) - $flds['COL_D_CREATE_TIME'] = 'order_by_desc'; - else - $flds['COL_D_CREATE_TIME'] = 'order_by_asc'; - break; - - case 'typename': - if ($sort_fld_val === false) - $flds['COL_DATA_TYPE_NAME'] = 'order_by_desc'; - else - $flds['COL_DATA_TYPE_NAME'] = 'order_by_asc'; - break; - - case 'owner': - if ($sort_fld_val === false) - $flds['COL_D_OWNER_NAME'] = 'order_by_desc'; - else - $flds['COL_D_OWNER_NAME'] = 'order_by_asc'; - break; - - case 'dirname': - if ($sort_fld_val === false) - $flds['COL_COLL_NAME'] = 'order_by_desc'; - else - $flds['COL_COLL_NAME'] = 'order_by_asc'; - break; - - default: - /* - throw new RODSException("Sort field name '$sort_fld_key' is not valid", - 'PERR_USER_INPUT_ERROR'); - break; - */ - } - } - $select = new RODSGenQueSelFlds(array_keys($flds), array_values($flds)); - - $descendantOnly = false; - $recursive = false; - $logicalFile = false; - $condition = new RODSGenQueConds(); - foreach ($terms as $term_key => $term_val) { - switch ($term_key) { - case 'name': - //$condition->add('COL_DATA_NAME', 'like', '%'.$term_val.'%'); - $condition->add('COL_DATA_NAME', 'like', $term_val); - break; - case 'smtime': - $condition->add('COL_D_MODIFY_TIME', '>=', $term_val); - break; - case 'emtime': - $condition->add('COL_D_MODIFY_TIME', '<', $term_val); - break; - case 'owner': - $condition->add('COL_D_OWNER_NAME', '=', $term_val); - break; - case 'ownerzone': - $condition->add('COL_D_OWNER_ZONE', '=', $term_val); - break; - case 'rescname': - $condition->add('COL_D_RESC_NAME', '=', $term_val); - break; - case 'metadata': - $meta_array = $term_val; - foreach ($meta_array as $meta) { - if (isset($meta->name)) { - if ($meta->nameop === 'like') { - $condition->add('COL_META_DATA_ATTR_NAME', 'like', '%' . $meta->name . '%'); - } else if (isset($meta->nameop)) { - $condition->add('COL_META_DATA_ATTR_NAME', $meta->nameop, $meta->name); - } else { - $condition->add('COL_META_DATA_ATTR_NAME', '=', $meta->name); - } - } - if (isset($meta->value)) { - if ($meta->op === 'like') { - $condition->add('COL_META_DATA_ATTR_VALUE', 'like', '%' . $meta->value . '%'); - } else if (isset($meta->op)) { - $condition->add('COL_META_DATA_ATTR_VALUE', $meta->op, $meta->value); - } else { - $condition->add('COL_META_DATA_ATTR_VALUE', '=', $meta->value); - } - } - if (isset($meta->unit)) { - if ($meta->unitop === 'like') { - $condition->add('COL_META_DATA_ATTR_UNIT', 'like', '%' . $meta->unit . '%'); - } else if (isset($meta->unitop)) { - $condition->add('COL_META_DATA_ATTR_UNIT', $meta->unitop, $meta->unit); - } else { - $condition->add('COL_META_DATA_ATTR_UNIT', '=', $meta->unit); - } - } - } - break; - - case 'descendantOnly': - if (true === $term_val) - $descendantOnly = true; - break; - - case 'recursive': - if (true === $term_val) - $recursive = true; - break; - - case 'logicalFile': - if (true === $term_val) - $logicalFile = true; - break; - - default: - throw new RODSException("Term field name '$term_key' is not valid", - 'PERR_USER_INPUT_ERROR'); - break; - } - } - - if ($descendantOnly === true) { - if ($recursive === true) - $condition->add('COL_COLL_NAME', 'like', $this->path_str . '/%', - array(array('op' => '=', 'val' => $this->path_str))); - else - $condition->add('COL_COLL_NAME', '=', $this->path_str); - } - - if ($logicalFile === true) { - $select->update('COL_D_RESC_NAME', 'count'); - $select->update('COL_DATA_SIZE', 'max'); - $select->update('COL_D_CREATE_TIME', 'min'); - $select->update('COL_D_MODIFY_TIME', 'max'); - } - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $results = $conn->query($select, $condition, $start, $limit); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - - $total_count = $results->getTotalCount(); - $result_values = $results->getValues(); - $found = array(); - for ($i = 0; $i < $results->getNumRow(); $i++) { - $resc_name = ($logicalFile === true) ? NULL : $result_values['COL_D_RESC_NAME'][$i]; - $num_replica = ($logicalFile === true) ? intval($result_values['COL_D_RESC_NAME'][$i]) : NULL; - $stats = new RODSFileStats( - $result_values['COL_DATA_NAME'][$i], - $result_values['COL_DATA_SIZE'][$i], - $result_values['COL_D_OWNER_NAME'][$i], - $result_values['COL_D_OWNER_ZONE'][$i], - $result_values['COL_D_MODIFY_TIME'][$i], - $result_values['COL_D_CREATE_TIME'][$i], - $result_values['COL_D_DATA_ID'][$i], - $result_values['COL_DATA_TYPE_NAME'][$i], - $resc_name, - $result_values['COL_D_COMMENTS'][$i], - $num_replica - ); - - if ($result_values['COL_COLL_NAME'][$i] == '/') - $full_path = '/' . $result_values['COL_DATA_NAME'][$i]; - else - $full_path = $result_values['COL_COLL_NAME'][$i] . '/' . - $result_values['COL_DATA_NAME'][$i]; - $found[] = new ProdsFile($this->account, $full_path, false, $stats); - } - return $found; - } - - /** - * query metadata, and find matching diretories. - * @param array $terms an assositive array of search conditions, supported ones are: - * - 'name' (string) - partial name of the target (file or dir) - * - 'descendantOnly' (boolean) - whether to search among this directory's decendents. default is false. - * - 'recursive' (boolean) - whether to search recursively, among all decendents and their children. default is false. This option only works when 'descendantOnly' is true - * - 'smtime' (int) - start last-modified-time in unix timestamp. The specified time is included in query, in other words the search can be thought was "mtime >= specified time" - * - 'emtime' (int) - end last-modified-time in unix timestamp. The specified time is not included in query, in other words the search can be thought was "mtime < specified time" - * - 'owner' (string) - owner name of the dir - * - 'metadata' (array of RODSMeta) - array of metadata. - * @param int &$total_count This value (passed by reference) returns the total potential count of search results - * @param int $start starting index of search results. - * @param int $limit up to how many results to be returned. If negative, give all results back. - * @param array $sort_flds associative array with following keys: - * - 'name' - name of the dir - * - 'mtime' - last modified time - * - 'ctime' - creation time - * - 'owner' - owner of the dir - * The results are sorted by specified array keys. - * The possible array value must be boolean: true stands for 'asc' and false stands for 'desc', default is 'asc' - * @return array of ProdsPath objects (ProdsFile or ProdsDir). - */ - public function findDirs(array $terms, &$total_count, $start = 0, $limit = -1, - array $sort_flds = array()) - { - $flds = array("COL_COLL_NAME" => NULL, "COL_COLL_ID" => NULL, - "COL_COLL_OWNER_NAME" => NULL, 'COL_COLL_OWNER_ZONE' => NULL, - "COL_COLL_CREATE_TIME" => NULL, "COL_COLL_MODIFY_TIME" => NULL, - "COL_COLL_COMMENTS" => NULL); - - foreach ($sort_flds as $sort_fld_key => $sort_fld_val) { - switch ($sort_fld_key) { - case 'name': - if ($sort_fld_val === false) - $flds['COL_COLL_NAME'] = 'order_by_desc'; - else - $flds['COL_COLL_NAME'] = 'order_by_asc'; - break; - - case 'mtime': - if ($sort_fld_val === false) - $flds['COL_COLL_MODIFY_TIME'] = 'order_by_desc'; - else - $flds['COL_COLL_MODIFY_TIME'] = 'order_by_asc'; - break; - - case 'ctime': - if ($sort_fld_val === false) - $flds['COL_COLL_CREATE_TIME'] = 'order_by_desc'; - else - $flds['COL_COLL_CREATE_TIME'] = 'order_by_asc'; - break; - - case 'owner': - if ($sort_fld_val === false) - $flds['COL_COLL_OWNER_NAME'] = 'order_by_desc'; - else - $flds['COL_COLL_OWNER_NAME'] = 'order_by_asc'; - break; - - default: - /* - throw new RODSException("Sort field name '$sort_fld_key' is not valid", - 'PERR_USER_INPUT_ERROR'); - */ - break; - } - } - $select = new RODSGenQueSelFlds(array_keys($flds), array_values($flds)); - - $descendantOnly = false; - $recursive = false; - $condition = new RODSGenQueConds(); - foreach ($terms as $term_key => $term_val) { - switch ($term_key) { - case 'name': - //$condition->add('COL_COLL_NAME', 'like', '%'.$term_val.'%'); - $condition->add('COL_COLL_NAME', 'like', $term_val); - break; - case 'smtime': - $condition->add('COL_COLL_MODIFY_TIME', '>=', $term_val); - break; - case 'emtime': - $condition->add('COL_COLL_MODIFY_TIME', '<', $term_val); - break; - case 'owner': - $condition->add('COL_COLL_OWNER_NAME', '=', $term_val); - break; - case 'metadata': - $meta_array = $term_val; - foreach ($meta_array as $meta) { - $condition->add('COL_META_COLL_ATTR_NAME', '=', $meta->name); - if (isset($meta->op)) - $op = $meta->op; - else - $op = '='; - if ($op == 'like') - //$value='%'.$meta->value.'%'; - $value = $meta->value; - else - $value = $meta->value; - $condition->add('COL_META_COLL_ATTR_VALUE', $op, $value); - } - break; - - case 'descendantOnly': - if (true === $term_val) - $descendantOnly = true; - break; - - case 'recursive': - if (true === $term_val) - $recursive = true; - break; - - default: - throw new RODSException("Term field name '$term_key' is not valid", - 'PERR_USER_INPUT_ERROR'); - break; - } - } - - if ($descendantOnly === true) { - // eliminate '/' from children, if current path is already root - if ($this->path_str == '/') - $condition->add('COL_COLL_NAME', '<>', '/'); - - if ($recursive === true) - $condition->add('COL_COLL_PARENT_NAME', 'like', $this->path_str . '/%', - array(array('op' => '=', 'val' => $this->path_str))); - else - $condition->add('COL_COLL_PARENT_NAME', '=', $this->path_str); - } - - $conn = RODSConnManager::getConn($this->account); - $results = $conn->query($select, $condition, $start, $limit); - RODSConnManager::releaseConn($conn); - - $total_count = $results->getTotalCount(); - $result_values = $results->getValues(); - $found = array(); - for ($i = 0; $i < $results->getNumRow(); $i++) { - $full_path = $result_values['COL_COLL_NAME'][$i]; - $acctual_name = basename($result_values['COL_COLL_NAME'][$i]); - $stats = new RODSDirStats( - $acctual_name, - $result_values['COL_COLL_OWNER_NAME'][$i], - $result_values['COL_COLL_OWNER_ZONE'][$i], - $result_values['COL_COLL_MODIFY_TIME'][$i], - $result_values['COL_COLL_CREATE_TIME'][$i], - $result_values['COL_COLL_ID'][$i], - $result_values['COL_COLL_COMMENTS'][$i]); - - $found[] = new ProdsDir($this->account, $full_path, false, $stats); - } - return $found; - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsFile.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/ProdsFile.class.php deleted file mode 100644 index 3fa5da0dcc..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsFile.class.php +++ /dev/null @@ -1,434 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ - -require_once("autoload.inc.php"); - -class ProdsFile extends ProdsPath -{ - public $stats; - - private $rodsconn; //real RODS connection - private $l1desc; //lvl 1 descriptor on RODS server - private $conn; //the connection to RODS agent l1desc lives on. - private $rescname; //resource name. - private $openmode; //open mode used if file is opened - private $position; //current position of the file, if opened. - - /** - * The class constructor - */ - public function __construct(RODSAccount &$account, $path_str, - $verify = false, RODSFileStats $stats = NULL) - { - $this->l1desc = -1; - $this->stats = $stats; - - if ($path_str{strlen($path_str) - 1} == '/') { - throw new RODSException("Invalid file name '$path_str' ", - 'PERR_USER_INPUT_PATH_ERROR'); - } - - parent::__construct($account, $path_str); - if ($verify === true) { - if ($this->exists() === false) { - throw new RODSException("File '$this' does not exist", - 'PERR_PATH_DOES_NOT_EXISTS'); - } - } - } - - - /** - * Create a new ProdsFile object from URI string. - * @param string $path the URI Sting - * @param boolean $verify whether verify if the path exsits - * @return a new ProdsDir - */ - public static function fromURI($path, $verify=false) - { - if (0!=strncmp($path,"rods://",7)) - $path="rods://".$path; - $url=parse_url($path); - - $host=isset($url['host'])?$url['host']:''; - $port=isset($url['port'])?$url['port']:''; - - $user=''; - $zone=''; - $authtype='irods'; - if (isset($url['user'])) - { - if (strstr($url['user'],".")!==false) { - $user_array=@explode(".",$url['user']); - if (count($user_array)===3) { - $user=$user_array[0]; - $zone=$user_array[1]; - $authtype=$user_array[2]; - } - else { - $user=$user_array[0]; - $zone=$user_array[1]; - } - } - else - $user=$url['user']; - } - - $pass=isset($url['pass'])?$url['pass']:''; - - $account=new RODSAccount($host, $port, $user, $pass, $zone, '', $authtype); - - $path_str=isset($url['path'])?$url['path']:''; - - // treat query and fragment as part of name - if (isset($url['query'])&&(strlen($url['query'])>0)) - $path_str=$path_str.'?'.$url['query']; - if (isset($url['fragment'])&&(strlen($url['fragment'])>0)) - $path_str=$path_str.'#'.$url['fragment']; - - if (empty($path_str)) - $path_str='/'; - - return (new ProdsFile($account,$path_str,$verify)); - } - - /** - * Verify if this file exist with server. This function shouldn't be called directly, use {@link exists} - */ - protected function verify() - { - $conn = RODSConnManager::getConn($this->account); - $this->path_exists= $conn -> fileExists ($this->path_str); - RODSConnManager::releaseConn($conn); - } - - /** - * get the file stats - */ - public function getStats() - { - $conn = RODSConnManager::getConn($this->account); - $stats=$conn->getFileStats($this->path_str); - RODSConnManager::releaseConn($conn); - - if ($stats===false) $this->stats=NULL; - else $this->stats=$stats; - return $this->stats; - } - - /** - * Open a file path (string) exists on RODS server. - * - * @param string $mode open mode. Supported modes are: - * - 'r' Open for reading only; place the file pointer at the beginning of the file. - * - 'r+' Open for reading and writing; place the file pointer at the beginning of the file. - * - 'w' Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it. - * - 'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it. - * - 'a' Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. - * - 'a+' Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. - * - 'x' Create and open for writing only; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. - * - 'x+' Create and open for reading and writing; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. - * @param string $rescname. Note that this parameter is required only if the file does not exists (create mode). If the file already exists, and if file resource is unknown or unique or you-dont-care for that file, leave the field, or pass NULL. - * @param boolean $assum_file_exists. This parameter specifies whether file exists. If the value is false, this mothod will check with RODS server to make sure. If value is true, the check will NOT be done. Default value is false. - * @param string $filetype. This parameter only make sense when you want to specify the file type, if file does not exists (create mode). If not specified, it defaults to "generic" - * @param integer $cmode. This parameter is only used for "createmode". It specifies the file mode on physical storage system (RODS vault), in octal 4 digit format. For instance, 0644 is owner readable/writeable, and nothing else. 0777 is all readable, writable, and excutable. If not specified, and the open flag requirs create mode, it defaults to 0644. - */ - public function open($mode, $rescname = NULL, - $assum_file_exists = false, $filetype = 'generic', $cmode = 0644) - { - if ($this->l1desc >= 0) - return; - - if (!empty($rescname)) - $this->rescname = $rescname; - - $this->conn = RODSConnManager::getConn($this->account); - $this->l1desc = $this->conn->openFileDesc($this->path_str, $mode, - $this->postion, $rescname, $assum_file_exists, $filetype, $cmode); - $this->openmode = $mode; - RODSConnManager::releaseConn($this->conn); - } - - /** - * get the file open mode, if opened previously - * @return string open mode, if not opened, it return NULL - */ - public function getOpenmode() - { - return $this->openmode; - } - - /** - * get the file current position, if opened previously - * @return string open mode, if not opened, it return NULL - */ - public function tell() - { - return $this->position; - } - - /** - * unlink the file on server - * @param string $rescname resource name. Not required if there is no other replica. - * @param boolean $force flag (true or false) indicating whether force delete or not. - */ - public function unlink($rescname = NULL, $force = false) - { - $conn = RODSConnManager::getConn($this->account); - $conn->fileUnlink($this->path_str, $rescname, $force); - RODSConnManager::releaseConn($conn); - } - /** - * close the file descriptor (private) made from RODS server earlier. - */ - public function close() - { - if ($this->l1desc >= 0) { - while ($this->conn->isIdle() === false) { - trigger_error("The connection is not available! sleep for a while and retry...", - E_USER_WARNING); - usleep(50); - } - $this->conn->lock(); - $this->conn->closeFileDesc($this->l1desc); - $this->conn->unlock(); - $this->conn = null; //release the connection - $this->l1desc = -1; - } - } - - /** - * reads up to length bytes from the file. Reading stops when up to length bytes have been read, EOF (end of file) is reached - * - * @param int $length up to how many bytes to read. - * @return the read string. - */ - public function read($length) - { - if ($this->l1desc < 0) { - throw new RODSException("File '$this' is not opened! l1desc=$this->l1desc", - 'PERR_USER_INPUT_ERROR'); - } - - while ($this->conn->isIdle() === false) { - trigger_error("The connection is not available! sleep for a while and retry...", - E_USER_WARNING); - usleep(50); - } - - $this->conn->lock(); - $retval = $this->conn->fileRead($this->l1desc, $length); - $this->position = $this->position + strlen($retval); - $this->conn->unlock(); - return $retval; - } - - /** - * write up to length bytes to the server. this function is binary safe. - * @param string $string contents to be written. - * @param int $length up to how many bytes to write. - * @return the number of bytes written. - */ - public function write($string, $length = NULL) - { - if ($this->l1desc < 0) { - throw new RODSException("File '$this' is not opened! l1desc=$this->l1desc", - 'PERR_USER_INPUT_ERROR'); - } - - while ($this->conn->isIdle() === false) { - trigger_error("The connection is not available! sleep for a while and retry...", - E_USER_WARNING); - usleep(50); - } - - $this->conn->lock(); - $retval = $this->conn->fileWrite($this->l1desc, $string, $length); - $this->position = $this->position + (int)$retval; - $this->conn->unlock(); - return $retval; - } - - /** - * Sets the file position for the file. The new position, measured in bytes from the beginning of the file, is obtained by adding offset to the position specified by whence, whose values are defined as follows: - * SEEK_SET - Set position equal to offset bytes. - * SEEK_CUR - Set position to current location plus offset. - * SEEK_END - Set position to end-of-file plus offset. (To move to a position before the end-of-file, you need to pass a negative value in offset.) - * If whence is not specified, it is assumed to be SEEK_SET. - * @return int the current offset - */ - public function seek($offset, $whence = SEEK_SET) - { - if ($this->l1desc < 0) { - throw new RODSException("File '$this' is not opened! l1desc=$this->l1desc", - 'PERR_USER_INPUT_ERROR'); - } - - while ($this->conn->isIdle() === false) { - trigger_error("The connection is not available! sleep for a while and retry...", - E_USER_WARNING); - usleep(50); - } - - $this->conn->lock(); - $retval = $this->conn->fileSeek($this->l1desc, $offset, $whence); - $this->position = (int)$retval; - $this->conn->unlock(); - return $retval; - } - - /** - * Sets the file position to the beginning of the file stream. - */ - public function rewind() - { - while ($this->conn->isIdle() === false) { - trigger_error("The connection is not available! sleep for a while and retry...", - E_USER_WARNING); - usleep(50); - } - - $this->seek(0, SEEK_SET); - $this->position = 0; - } - - /** - * get the file descriptor (private) made from RODS server earlier. - */ - public function getL1desc() - { - return $this->l1desc; - } - - /** - * Because RODS server can only do file operations in a single connection, a RODS - * connection is 'reserved' when file is opened, and released when closed. - */ - public function getConn() - { - return $this->conn; - } - - /** - * Replicate file to resources with options. - * @param string $desc_resc destination resource - * @param array $options an assosive array of options: - * - 'all' (boolean): only meaningful if input resource is a resource group. Replicate to all the resources in the resource group. - * - 'backupMode' (boolean): if a good copy already exists in this resource, don't make another copy. - * - 'admin' (boolean): admin user uses this option to backup/replicate other users files - * - 'replNum' (integer): the replica to copy, typically not needed - * - 'srcResc' (string): specifies the source resource of the data object to be replicate, only copies stored in this resource will be replicated. Otherwise, one of the copy will be replicated - * These options are all 'optional', if omitted, the server will try to do it anyway - * @return number of bytes written if success, in case of faliure, throw an exception - */ - public function repl($desc_resc, array $options = array()) - { - $conn = RODSConnManager::getConn($this->account); - $bytesWritten = $conn->repl($this->path_str, $desc_resc, $options); - RODSConnManager::releaseConn($conn); - - return $bytesWritten; - } - - /** - * get replica information for this file - * @return array of array, each child array is a associative and contains: - * [repl_num] : replica number - * [chk_sum] : checksum of the file - * [size] : size of the file (replica) - * [resc_name] : resource name - * [resc_repl_status] : replica status (dirty bit), whether this replica is dirty (modifed), and requirs synchs to other replicas. - * [resc_grp_name] : resource group name - * [resc_type] : resource type name - * [resc_class] : resource class name - * [resc_loc] : resource location - * [resc_freespace]: resource freespace - * [data_status] : data status - * [ctime] : data creation time (unix timestamp) - * [mtime] : data last modified time (unix timestamp) - */ - public function getReplInfo() - { - $select = new RODSGenQueSelFlds( - array("COL_DATA_REPL_NUM", "COL_D_DATA_CHECKSUM", 'COL_DATA_SIZE', - "COL_D_RESC_NAME", "COL_D_RESC_GROUP_NAME", - "COL_D_DATA_STATUS", "COL_D_CREATE_TIME", - "COL_D_MODIFY_TIME", 'COL_R_TYPE_NAME', 'COL_R_CLASS_NAME', - 'COL_R_LOC', 'COL_R_FREE_SPACE', 'COL_D_REPL_STATUS') - ); - $condition = new RODSGenQueConds( - array("COL_COLL_NAME", "COL_DATA_NAME"), - array("=", "="), - array($this->parent_path, $this->name) - ); - - $conn = RODSConnManager::getConn($this->account); - $que_result = $conn->query($select, $condition); - RODSConnManager::releaseConn($conn); - - $ret_arr = array(); - for ($i = 0; $i < $que_result->getNumRow(); $i++) { - $ret_arr_row = array(); - $que_result_val = $que_result->getValues(); - $ret_arr_row['repl_num'] = $que_result_val['COL_DATA_REPL_NUM'][$i]; - $ret_arr_row['chk_sum'] = $que_result_val['COL_D_DATA_CHECKSUM'][$i]; - $ret_arr_row['size'] = $que_result_val['COL_DATA_SIZE'][$i]; - $ret_arr_row['resc_name'] = $que_result_val['COL_D_RESC_NAME'][$i]; - $ret_arr_row['resc_grp_name'] = $que_result_val['COL_D_RESC_GROUP_NAME'][$i]; - $ret_arr_row['data_status'] = $que_result_val['COL_D_DATA_STATUS'][$i]; - $ret_arr_row['ctime'] = $que_result_val['COL_D_CREATE_TIME'][$i]; - $ret_arr_row['mtime'] = $que_result_val['COL_D_MODIFY_TIME'][$i]; - $ret_arr_row['resc_type'] = $que_result_val['COL_R_TYPE_NAME'][$i]; - $ret_arr_row['resc_class'] = $que_result_val['COL_R_CLASS_NAME'][$i]; - $ret_arr_row['resc_loc'] = $que_result_val['COL_R_LOC'][$i]; - $ret_arr_row['resc_freespace'] = $que_result_val['COL_R_FREE_SPACE'][$i]; - $ret_arr_row['resc_repl_status'] = $que_result_val['COL_D_REPL_STATUS'][$i]; - $ret_arr[] = $ret_arr_row; - } - return $ret_arr; - } - - /** - * Get ACL (users and their rights on a file) - * @param string $filepath input file path string - * @return RODSFileStats. If file does not exists, return fales. - */ - public function getACL() - { - - $filepath = $this->path_str; - $parent = dirname($filepath); - $filename = basename($filepath); - -// $cond = array(new RODSQueryCondition("COL_COLL_NAME", $parent), -// new RODSQueryCondition("COL_DATA_NAME", $filename)); - $cond = array(new RODSQueryCondition("COL_DATA_NAME", $filename), - new RODSQueryCondition("COL_COLL_NAME", $parent)); - - $connLocal = RODSConnManager::getConn($this->account); - $que_result = $connLocal->genQuery( - array("COL_USER_NAME", "COL_USER_ZONE", "COL_DATA_ACCESS_NAME"), - $cond, array()); - RODSConnManager::releaseConn($connLocal); - if ($que_result === false) return false; - - - for($i=0; $i < sizeof($que_result['COL_USER_NAME']); $i++) { - $users[] = (object) array( - "COL_USER_NAME" => $que_result['COL_USER_NAME'][$i], - "COL_USER_ZONE" => $que_result['COL_USER_ZONE'][$i], - "COL_DATA_ACCESS_NAME" => $que_result['COL_DATA_ACCESS_NAME'][$i] - ); - } - return $users; - } -} - - - - diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsPath.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/ProdsPath.class.php deleted file mode 100644 index fdf100b77a..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsPath.class.php +++ /dev/null @@ -1,281 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ - -require_once("autoload.inc.php"); - -require_once(CLASS_DIR . "/ProdsConfig.inc.php"); - -/** - * ProdsPath class. This class is a abastract class for objects that can be represented as a path, such as file or directory - * @package Prods - */ -abstract class ProdsPath -{ - /** - * string path - * @var string - */ - public $path_str; - - public $account; - - protected $path_exists; - - protected $parent_path; - protected $name; - - /** - * Default Constructor. Because this class is abstract, this constructor should not be called directly. - * - * @param RODSAccount account iRODS account used for connection - * @param string $path_str the path of this dir - * @return ProdsPath a new ProdsPath - */ - public function __construct(RODSAccount &$account, $path_str) - { - $this->account = $account; - - // strip the tailing "/" - while ((strlen($path_str) > 1) && ($path_str{strlen($path_str) - 1} == '/')) { - $path_str = substr($path_str, 0, strlen($path_str) - 1); - } - // remove duplicate '/' characters - $path_str = str_replace('//', '/', $path_str); - $this->path_str = $path_str; - if ($path_str == '/') { - $this->parent_path = null; - } else { - $this->parent_path = dirname($this->path_str); - } - $this->name = basename($this->path_str); - } - - public function __toString() - { - return $this->account . $this->path_str; - } - - /** - * Whether this path (dir or file) exists on the server. - * @return boolean - */ - public function exists() - { - if (isset($this->path_exists)) - return $this->path_exists; - - else { - $this->verify(); - return $this->path_exists; - } - } - - /** - * Verify if a path exist with server. This function shouldn't be called directly, use {@link exists} - */ - abstract protected function verify(); - - /** - * Get meta data of this path (file or dir). - * @return array array of RODSMeta. - */ - //public function getMeta() - public function getMeta($get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if ($this instanceof ProdsFile) - $type = 'd'; - else - if ($this instanceof ProdsDir) - $type = 'c'; - else - throw new RODSException("Unsupported data type:" . get_class($this), - "PERR_INTERNAL_ERR"); - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $meta_array = $conn->getMeta($type, $this->path_str); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - return $meta_array; - } - - /** - * update metadata to this path (file or dir) - */ - public function updateMeta(RODSMeta $meta_old, RODSMeta $meta_new) - { - $this->rmMeta($meta_old); - $this->addMeta($meta_new); - } - - /** - * Add metadata to this path (file or dir) - */ - // public function addMeta(RODSMeta $meta) - public function addMeta(RODSMeta $meta, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if ($this instanceof ProdsFile) - $type = 'd'; - else - if ($this instanceof ProdsDir) - $type = 'c'; - else - throw new RODSException("Unsupported data type:" . get_class($this), - "PERR_INTERNAL_ERR"); - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->addMeta($type, $this->path_str, $meta); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - } - - /** - * remove metadata to this path (file or dir) - */ - // public function rmMeta(RODSMeta $meta) - public function rmMeta(RODSMeta $meta, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if ($this instanceof ProdsFile) - $type = 'd'; - else - if ($this instanceof ProdsDir) - $type = 'c'; - else - throw new RODSException("Unsupported data type:" . get_class($this), - "PERR_INTERNAL_ERR"); - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->rmMeta($type, $this->path_str, $meta); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - } - - /** - * remove metadata of this path (file or dir) by id - * @param integer metaid id of the metadata entry - */ - // public function rmMetaByID ($metaid) - public function rmMetaByID($metaid, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if ($this instanceof ProdsFile) - $type = 'd'; - else - if ($this instanceof ProdsDir) - $type = 'c'; - else - throw new RODSException("Unsupported data type:" . get_class($this), - "PERR_INTERNAL_ERR"); - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->rmMetaByID($type, $this->path_str, $metaid); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - } - - /** - * copy meta data from this path (file or dir) to $dest path - */ - // public function cpMeta(ProdsPath $dest) - public function cpMeta(ProdsPath $dest, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if ($this instanceof ProdsFile) - $type_src = 'd'; - else - if ($this instanceof ProdsDir) - $type_src = 'c'; - else - throw new RODSException("Unsupported data type:" . get_class($this), - "PERR_INTERNAL_ERR"); - - if ($dest instanceof ProdsFile) - $type_dest = 'd'; - else - if ($dest instanceof ProdsDir) - $type_dest = 'c'; - else - throw new RODSException("Unsupported data type:" . get_class($this), - "PERR_INTERNAL_ERR"); - - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->cpMeta($type_src, $type_dest, $this->path_str, $dest->path_str); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - } - - /** - * rename this path (file of dir) - * @param string $new_path_str new path string to be renamed to. - */ - // public function rename($new_path_str) - public function rename($new_path_str, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - if ($this instanceof ProdsFile) - $type = 0; - else - $type = 1; - //$conn = RODSConnManager::getConn($this->account); - $conn = call_user_func_array($get_cb, array(&$this->account)); - $conn->rename($this->path_str, $new_path_str, $type); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - $this->path_str = $new_path_str; - $this->parent_path = dirname($this->path_str); - $this->name = basename($this->path_str); - } - - /** - * Get name of this path. note that this is not the full path. for instance if path is "/foo/bar", the name is "bar" - * @return string name of the path. - */ - public function getName() - { - return $this->name; - } - - /** - * Get string form of this path. note that this is the full path. - * @return string form of the path. - */ - public function getPath() - { - return $this->path_str; - } - - /** - * Get parent's path of this path. - * @return string parent's path. - */ - public function getParentPath() - { - return $this->parent_path; - } - - /** - * Get URI of this path. - * @return string this path's URI. - */ - public function toURI() - { - return $this->account->toURI() . $this->path_str; - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsQuery.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/ProdsQuery.class.php deleted file mode 100644 index 5e8dc92d59..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsQuery.class.php +++ /dev/null @@ -1,105 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ -require_once("autoload.inc.php"); - -class ProdsQuery -{ - public $account; - - public function __construct(RODSAccount $account) - { - $this->account = $account; - } - - /** - * Get all user defined metadata names for all files on the server. - * @return array of strings (metadata names). - */ - public function getMetadataNamesForAllFiles() - { - $flds = array("COL_META_DATA_ATTR_NAME" => NULL); - $select = new RODSGenQueSelFlds(array_keys($flds), array_values($flds)); - $condition = new RODSGenQueConds(); - $condition->add('COL_D_DATA_ID', '>=', '0'); - $conn = RODSConnManager::getConn($this->account); - $results = $conn->query($select, $condition); - RODSConnManager::releaseConn($conn); - - if ($results->getNumRow() < 1) - return array(); - else { - $values = $results->getValues(); - return $values['COL_META_DATA_ATTR_NAME']; - } - } - - /** - * Get all user defined metadata names for all directories(collections) on the server. - * @return array of strings (metadata names). - */ - public function getMetadataNamesForAllDirs() - { - $flds = array("COL_META_COLL_ATTR_NAME" => NULL); - $select = new RODSGenQueSelFlds(array_keys($flds), array_values($flds)); - $condition = new RODSGenQueConds(); - $condition->add('COL_COLL_ID', '>=', '0'); - $conn = RODSConnManager::getConn($this->account); - $results = $conn->query($select, $condition); - RODSConnManager::releaseConn($conn); - - if ($results->getNumRow() < 1) - return array(); - else { - $values = $results->getValues(); - return $values['COL_META_COLL_ATTR_NAME']; - } - } - - /** - * Get all resources registered on the server - * @return array with fields: id, name, type, zone, class, loc, info, comment, ctime, mtime, vault_path, free_space. If user not found return empty array. - */ - public function getResources() - { - // set selected value - $flds = array("COL_R_RESC_ID" => NULL, "COL_R_RESC_NAME" => NULL, - "COL_R_ZONE_NAME" => NULL, "COL_R_TYPE_NAME" => NULL, - "COL_R_CLASS_NAME" => NULL, "COL_R_LOC" => NULL, - "COL_R_VAULT_PATH" => NULL, "COL_R_FREE_SPACE" => NULL, - "COL_R_RESC_INFO" => NULL, "COL_R_RESC_COMMENT" => NULL, - "COL_R_CREATE_TIME" => NULL, "COL_R_MODIFY_TIME" => NULL); - $select = new RODSGenQueSelFlds(array_keys($flds), array_values($flds)); - $condition = new RODSGenQueConds(); - $conn = RODSConnManager::getConn($this->account); - $results = $conn->query($select, $condition); - RODSConnManager::releaseConn($conn); - $result_vals = $results->getValues(); - $retval = array(); - for ($i = 0; $i < $results->getNumRow(); $i++) { - $retval_row = array(); - $retval_row['id'] = $result_vals["COL_R_RESC_ID"][$i]; - $retval_row['name'] = $result_vals["COL_R_RESC_NAME"][$i]; - $retval_row['type'] = $result_vals["COL_R_TYPE_NAME"][$i]; - $retval_row['zone'] = $result_vals["COL_R_ZONE_NAME"][$i]; - $retval_row['class'] = $result_vals["COL_R_CLASS_NAME"][$i]; - $retval_row['loc'] = $result_vals["COL_R_LOC"][$i]; - $retval_row['info'] = $result_vals["COL_R_RESC_INFO"][$i]; - $retval_row['comment'] = $result_vals["COL_R_RESC_COMMENT"][$i]; - $retval_row['ctime'] = $result_vals["COL_R_CREATE_TIME"][$i]; - $retval_row['mtime'] = $result_vals["COL_R_MODIFY_TIME"][$i]; - $retval_row['vault_path'] = $result_vals["COL_R_VAULT_PATH"][$i]; - $retval_row['free_space'] = $result_vals["COL_R_FREE_SPACE"][$i]; - $retval[] = $retval_row; - } - return $retval; - - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsRule.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/ProdsRule.class.php deleted file mode 100644 index d14d87ad1a..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsRule.class.php +++ /dev/null @@ -1,60 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ -require_once("autoload.inc.php"); - -class ProdsRule -{ - public $account; - public $body; - public $inp_params; - public $out_params; - public $remotesvr; - public $options; - - /* - * @param RODSAccount account this is the account used to connect to iRODS server - * @param string $rule_body body of the rule. Read this tutorial for details about rules: http://www.irods.org/index.php/Executing_user_defined_rules/workflow - * @param array $inp_params associative array defining input parameters for micro services used in this rule. only string and keyval pair are supported at this time. If the array value is a string, then type is string, if the array value is an RODSKeyValPair object, it will be treated a keyval pair - * @param array $out_params an array of names (strings) - * @param array $remotesvr if this rule need to run at remote server, this associative array should have the following keys: - * - 'host' remote host name or address - * - 'port' remote port - * - 'zone' remote zone - * if any of the value is empty, this option will be ignored. - * @param RODSKeyValPair $options an RODSKeyValPair specifying additional options, purpose of this is unknown at the developement time. Leave it alone if you are as clueless as me... - */ - public function __construct(RODSAccount $account, $rule_body, - array $inp_params = array(), array $out_params = array(), - array $remotesvr = array(), RODSKeyValPair $options = null) - { - $this->account = $account; - $this->rule_body = $rule_body; - $this->inp_params = $inp_params; - $this->out_params = $out_params; - $this->remotesvr = $remotesvr; - if (isset($options)) - $this->options = $options; - else - $this->options = new RODSKeyValPair(); - } - - /** - * Excute the rule, assign - * @return an associative array. Each array key is the lable, and each array value's type will depend on the type of $out_param, at this moment, only string and RODSKeyValPair are supported - */ - public function execute() - { - $conn = RODSConnManager::getConn($this->account); - $result = $conn->execUserRule($this->rule_body, $this->inp_params, - $this->out_params, $this->remotesvr, $this->options = null); - RODSConnManager::releaseConn($conn); - - return $result; - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsStreamer.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/ProdsStreamer.class.php deleted file mode 100644 index 67ef096c5c..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsStreamer.class.php +++ /dev/null @@ -1,434 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ - -require_once("autoload.inc.php"); - -class ProdsStreamer -{ - /** - * current position of the file or dir - * - * @access private - */ - private $position; - - /** - * Name of the directory/collection specified in the URI to opendir(). - * - * @access private - */ - private $dir; - - /** - * Name of the file specified in the URI to fopen(). - * - * @access private - */ - private $file; - - - /** - * url_stat() handler. - * - * @access private - */ - public function url_stat($path) - { - try { - $file=ProdsDir::fromURI($path); - $conn = RODSConnManager::getConn($file->account); - - $stats = $this->stat_file($conn, $file->path_str); - if (!$stats) { - $stats = $this->stat_dir($conn, $file->path_str); - } - - RODSConnManager::releaseConn($conn); - - return $stats; - - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * @param $conn - * @param $file - * @return mixed - */ - private function stat_dir($conn, $path_str) { - try { - $irods_stats = $conn->getDirStats($path_str); - if (!$irods_stats) - return false; - $stats = array(); - $stats[0] = $stats['dev'] = 0; - $stats[1] = $stats['ino'] = 0; - $stats[2] = $stats['mode'] = octdec('040755'); - $stats[3] = $stats['nlink'] = 1; - $stats[4] = $stats['uid'] = 0; - $stats[5] = $stats['gid'] = 0; - $stats[6] = $stats['rdev'] = -1; - $stats[7] = $stats['size'] = 0; - $stats[8] = $stats['atime'] = time(); - $stats[9] = $stats['mtime'] = $irods_stats->mtime; - $stats[10] = $stats['ctime'] = $irods_stats->ctime; - $stats[11] = $stats['blksize'] = -1; - $stats[12] = $stats['blocks'] = -1; - return $stats; - } catch (Exception $e) { - trigger_error("Got an exception: $e", E_USER_WARNING); - return false; - } - } - - /** - * @param $conn - * @param $file - * @return mixed - */ - private function stat_file($conn, $path_str) { - try { - $irods_stats = $conn->getFileStats($path_str); - if (!$irods_stats) - return false; - $stats = array(); - $stats[0] = $stats['dev'] = 0; - $stats[1] = $stats['ino'] = 0; - $stats[2] = $stats['mode'] = octdec('100644'); - $stats[3] = $stats['nlink'] = 1; - $stats[4] = $stats['uid'] = 0; - $stats[5] = $stats['gid'] = 0; - $stats[6] = $stats['rdev'] = -1; - $stats[7] = $stats['size'] = $irods_stats->size; - $stats[8] = $stats['atime'] = time(); - $stats[9] = $stats['mtime'] = $irods_stats->mtime; - $stats[10] = $stats['ctime'] = $irods_stats->ctime; - $stats[11] = $stats['blksize'] = -1; - $stats[12] = $stats['blocks'] = -1; - return $stats; - } catch (Exception $e) { - trigger_error("Got an exception: $e", E_USER_WARNING); - return false; - } - } - - /** - * mkdir() handler. - * - * @access private - */ - function mkdir ($url, $mode, $options) { - try { - $file=ProdsDir::fromURI($url); - $conn = RODSConnManager::getConn($file->account); - $conn->mkdir($file->path_str); - - RODSConnManager::releaseConn($conn); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * rmdir() handler - * - * @param $url - * @return bool - */ - function rmdir ($url) { - try { - $file=ProdsDir::fromURI($url); - $conn = RODSConnManager::getConn($file->account); - $conn->rmdir($file->path_str); - - RODSConnManager::releaseConn($conn); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * unlink() handler. - * - * @access private - */ - function unlink ($url) { - try { - $file=ProdsDir::fromURI($url); - $conn = RODSConnManager::getConn($file->account); - if (is_dir($url)) { - $conn->rmdir($file->path_str, true, true); - } else { - $conn->fileUnlink($file->path_str, NULL, true); - } - - RODSConnManager::releaseConn($conn); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * rename() handler. - * - * @access private - */ - function rename ($url_from, $url_to) { - try { - $file_from=ProdsDir::fromURI($url_from); - $file_to=ProdsDir::fromURI($url_to); - $conn = RODSConnManager::getConn($file_from->account); - - if (is_dir($url_from)) { - $conn->rename($file_from->path_str, $file_to->path_str, 0); - } else { - $conn->rename($file_from->path_str, $file_to->path_str, 1); - } - - RODSConnManager::releaseConn($conn); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * opendir() handler. - * - * @access private - */ - public function dir_opendir ($path, $options) - { - try { - $this->dir=ProdsDir::fromURI($path,true); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * readdir() handler. - * - * @access private - */ - public function dir_readdir() - { - try { - $child = $this->dir->getNextChild(); - if ($child === false) return false; - return $child->getName(); - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * fread() and fgets() handler. - * - * @access private - */ - public function stream_read ($count) { - if (in_array ($this->file->getOpenMode(), array ('w', 'a', 'x'))) { - return false; - } - try { - $ret = $this->file->read($count); - $this->position=$this->file->tell(); - return $ret; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * fwrite() handler. - * - * @access private - */ - public function stream_write ($data) { - if ($this->file->getOpenMode() =='r') { - return false; - } - try { - $ret = $this->file->write($data); - $this->position=$this->file->tell(); - return $ret; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - /** - * rewinddir() handler. - * - * @access private - */ - public function dir_rewinddir() - { - try { - $this->dir->rewind(); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * closedir() handler. - * - * @access private - */ - public function dir_closedir() - { - try { - $this->dir->rewind(); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * fopen() handler. - * - * @access private - */ - public function stream_open($path, $mode, $options, &$opened_path) - { - - // get rid of tailing 'b', if any. - if (($mode{strlen($mode) - 1} == 'b') && (strlen($mode) > 1)) - $mode = substr($mode, 0, strlen($mode) - 1); - try { - $this->file = ProdsFile::fromURI($path); - $this->file->open($mode); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * fstat() handler. - * - * @access private - */ - function stream_stat () { - - try { - $stats=$this->file->getStats(); - return array ( - -1, -1, -1, -1, -1, -1, $stats->size, time (), $stats->mtime, $stats->ctime, -1, -1, - 'dev' => -1, - 'ino' => -1, - 'mode' => -1, - 'nlink' => -1, - 'uid' => -1, - 'gid' => -1, - 'rdev' => -1, - 'size' => $stats->size, - 'atime' => time (), - 'mtime' => $stats->mtime, - 'ctime' => $stats->ctime, - 'blksize' => -1, - 'blocks' => -1, - ); - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * fclose() handler. - * - * @access private - */ - function stream_close () { - $this->file->close(); - $this->position = 0; - $this->file = null; - $this->dir = null; - } - - /** - * ftell() handler. - * - * @access private - */ - function stream_tell() - { - return $this->position; - } - - /** - * feof() handler. - * - * @access private - */ - function stream_eof() - { - try { - $stats = $this->file->getStats(); - return $this->position >= $stats->size; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return true; - } - } - - /** - * fseek() handler. - * - * @access private - */ - function stream_seek($offset, $whence) - { - try { - $this->file->seek($offset, $whence); - return true; - } catch (Exception $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - return false; - } - } - - /** - * fflush() handler. Please Note: This method must be called for any - * changes to be committed to the repository. - * - * @access private - */ - function stream_flush() - { - return true; - } -} - -stream_wrapper_register('rods', 'ProdsStreamer') - or die ('Failed to register protocol:rods'); -stream_wrapper_register('rods+ticket', 'ProdsStreamer') - or die ('Failed to register protocol:rods'); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsTicket.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/ProdsTicket.class.php deleted file mode 100644 index 0038a9c073..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/ProdsTicket.class.php +++ /dev/null @@ -1,41 +0,0 @@ - - * Date: 30.01.13 - * Time: 14:15 - */ - -require_once("autoload.inc.php"); - -class ProdsTicket -{ - private $account; - - public function __construct( RODSAccount &$account ) - { - $this->account = $account; - } - - /* - * This is just a stupid wrapper - * It proxifies RODSConn->createTicket - */ - public function createTicket( $object, $permission = 'read', $ticket = '' ) - { - $conn = RODSConnManager::getConn($this->account); - $ticket = $conn->createTicket($object, $permission, $ticket ); - RODSConnManager::releaseConn($conn); - return $ticket; - } - - /* - * This is also a stupid wrapper - * It proxifies RODSConn->deleteTicket - */ - public function deleteTicket( $ticket ) - { - $conn = RODSConnManager::getConn($this->account); - $ticket = $conn->deleteTicket( $ticket ); - RODSConnManager::releaseConn($conn); - } -} \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSAccount.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSAccount.class.php deleted file mode 100644 index ba4c5ad96b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSAccount.class.php +++ /dev/null @@ -1,201 +0,0 @@ -host=$host; - $this->port=$port; - $this->user=$user; - $this->pass=$pass; - $this->zone=$zone; - $this->default_resc=$default_resc; - $this->auth_type=$auth_type; - $this->ticket = $ticket; - } - - /** - * Create a RODSAccount object from URI string. - * @param string $uri - * @return a new RODSAccount object - */ - public static function fromURI($uri) - { - $url=parse_url($uri); - - $host=isset($url['host'])?$url['host']:''; - $port=isset($url['port'])?$url['port']:''; - - $user=''; - $zone=''; - $authtype='irods'; - if (isset($url['user'])) - { - if (strstr($url['user'],".")!==false) { - $user_array=@explode(".",$url['user']); - if (count($user_array)===3) { - $user=$user_array[0]; - $zone=$user_array[1]; - $authtype=$user_array[2]; - } - else { - $user=$user_array[0]; - $zone=$user_array[1]; - } - } - else - $user=$url['user']; - } - - $pass=isset($url['pass'])?$url['pass']:''; - - return (new RODSAccount($host, $port, $user, $pass, $zone, "", $authtype,$ticket = '')); - } - - - - public function equals(RODSAccount $other) - { - if (!isset($other)) - return false; - - if (($this->host == $other->host) && - ($this->port == $other->port) && - ($this->user == $other->user) - ) { - $ret_val = true; - } else - $ret_val = false; - - //echo ( "$this->host,$this->port,$this->user vs. $other->host,$other->port,$other->user = $ret_val"); - //flush(); - return $ret_val; - } - - public function getSignature() - { - return (bin2hex(md5("$this->user.$this->zone:this->pass@$this->host:$this->port.$this->ticket", TRUE))); - } - - public function __toString() - { - return "$this->user.$this->zone:(password hidden)@$this->host:$this->port"; - } - - public function toURI() - { - return ($this->user . - (empty($this->zone) ? '' : '.' . $this->zone) . - "@" . $this->host . ":" . $this->port); - } - - /** - * Get user information - * @param string username, if not specified, it will use current username instead - * @return array with fields: id, name, type, zone, dn, info, comment, ctime, mtime. If user not found return empty array. - */ - public function getUserInfo($username = NULL, - $get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - //$conn = RODSConnManager::getConn($this); - $conn = call_user_func_array($get_cb, array(&$this)); - //TODO: Overcome fear of passing $this by reference or stop passing $this by reference - $userinfo = $conn->getUserInfo($username); - //RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - if ((!empty($userinfo)) && (!empty($userinfo['zone']))) - $this->zone = $userinfo['zone']; - return $userinfo; - } - - /** - * Get a temp password for current user - * @return string of temp password - */ - public function getTempPassword($get_cb = array('RODSConnManager', 'getConn'), - $rel_cb = array('RODSConnManager', 'releaseConn')) - { - //$conn = RODSConnManager::getConn($this); - $conn = call_user_func_array($get_cb, array(&$this)); - //TODO: Overcome fear of passing $this by reference or stop passing $this by reference - $temppass = $conn->getTempPassword(); - // RODSConnManager::releaseConn($conn); - call_user_func($rel_cb, $conn); - return $temppass; - } - - /** - * Get user's home directory - * @param string init_path, if specified, it will overwrite the default path - * @return ProdsDir User's home directory - */ - public function getUserHomeDir($init_path = NULL) - { - if (empty($this->zone)) - $this->getUserInfo(); - if (isset($init_path)) { - $dir = new ProdsDir($this, $init_path); - if ($dir->exists()) { - return $dir; - } - } - return new ProdsDir($this, "/$this->zone/home/$this->user"); - } - - /** - * Get user's home directory URI - * @param string init_path, if specified, it will overwrite the default path - * @return String User's home - */ - public function getUserHomeDirURI($init_path = NULL) - { - $dir = $this->getUserHomeDir($init_path); - return $dir->toURI(); - } - - /** - * Get user's trash directory - * @return ProdsDir User's trash dir - */ - public function getUserTrashDir() - { - if (empty($this->zone)) - $this->getUserInfo(); - return new ProdsDir($this, "/$this->zone/trash/home/$this->user"); - } - - /** - * Get user's trash directory URI - * @return String User's trash URI - */ - public function getUserTrashDirURI() - { - $dir = $this->getUserTrashDir(); - return $dir->toURI(); - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSConn.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSConn.class.php deleted file mode 100644 index c10f880a5c..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSConn.class.php +++ /dev/null @@ -1,1613 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package RODSConn - */ - - -require_once("autoload.inc.php"); -require_once("RodsAPINum.inc.php"); -require_once("RodsConst.inc.php"); - -if (!defined("O_RDONLY")) define ("O_RDONLY", 0); -if (!defined("O_WRONLY")) define ("O_WRONLY", 1); -if (!defined("O_RDWR")) define ("O_RDWR", 2); -if (!defined("O_TRUNC")) define ("O_TRUNC", 512); - -class RODSConn -{ - private $conn; // (resource) socket connection to RODS server - - private $account; // RODS user account - - private $idle; - private $id; - - public $connected; - - /** - * Makes a new connection to RODS server, with supplied user information (name, passwd etc.) - * @param string $host hostname - * @param string $port port number - * @param string $user username - * @param string $pass passwd - * @param string $zone zonename - */ - public function __construct(RODSAccount &$account) - { - $this->account=$account; - $this->connected=false; - $this->conn=NULL; - $this->idle=true; - } - - public function __destruct() - { - if ($this->connected===true) - $this->disconnect(); - } - - public function equals(RODSConn $other) - { - return $this->account->equals($other->account); - } - - public function getSignature() - { - return $this->account->getSignature(); - } - - public function lock() - { - $this->idle=false; - } - - public function unlock() - { - $this->idle=true; - } - - public function isIdle() - { - return ($this->idle); - } - - public function getId() - { - return $this->id; - } - - public function setId($id) - { - $this->id=$id; - } - - public function getAccount() - { - return $this->account; - } - - public function connect() - { - $host=$this->account->host; - $port=$this->account->port; - $user=$this->account->user; - $pass=$this->account->pass; - $zone=$this->account->zone; - $auth_type = $this->account->auth_type; - - // if we're going to use PAM, set up the socket context - // options for SSL connections when we open the connection - if (strcasecmp($auth_type, "PAM") == 0) { - $ssl_opts = array('ssl' => array()); - if (array_key_exists('ssl', $GLOBALS['PRODS_CONFIG'])) { - $ssl_conf = $GLOBALS['PRODS_CONFIG']['ssl']; - if (array_key_exists('verify_peer', $ssl_conf)) { - if (strcasecmp("true", $ssl_conf['verify_peer']) == 0) { - $ssl_opts['ssl']['verify_peer'] = true; - } - } - if (array_key_exists('allow_self_signed', $ssl_conf)) { - if (strcasecmp("true", $ssl_conf['allow_self_signed']) == 0) { - $ssl_opts['ssl']['allow_self_signed'] = true; - } - } - if (array_key_exists('cafile', $ssl_conf)) { - $ssl_opts['ssl']['cafile'] = $ssl_conf['cafile']; - } - if (array_key_exists('capath', $ssl_conf)) { - $ssl_opts['ssl']['capath'] = $ssl_conf['capath']; - } - } - $ssl_ctx = stream_context_get_default($ssl_opts); - $sock_timeout = ini_get("default_socket_timeout"); - $conn = @stream_socket_client("tcp://$host:$port", $errno, $errstr, - $sock_timeout, STREAM_CLIENT_CONNECT, $ssl_ctx); - } - else { - $conn = @fsockopen($host, $port, $errno, $errstr); - } - if (!$conn) - throw new RODSException("Connection to '$host:$port' failed.1: ($errno)$errstr. ", - "SYS_SOCK_OPEN_ERR"); - $this->conn=$conn; - - // connect to RODS server - $msg=RODSMessage::packConnectMsg($user,$zone); - fwrite($conn, $msg); - - $msg=new RODSMessage(); - $intInfo=$msg->unpack($conn); - if ($intInfo<0) - { - throw new RODSException("Connection to '$host:$port' failed.2. User: $user Zone: $zone", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - - // are we doing PAM authentication - if (strcasecmp($auth_type, "PAM") == 0) - { - // Ask server to turn on SSL - $req_packet = new RP_sslStartInp(); - $msg=new RODSMessage("RODS_API_REQ_T", $req_packet, - $GLOBALS['PRODS_API_NUMS']['SSL_START_AN']); - fwrite($conn, $msg->pack()); - $msg=new RODSMessage(); - $intInfo=$msg->unpack($conn); - if ($intInfo<0) - { - throw new RODSException("Connection to '$host:$port' failed.ssl1. User: $user Zone: $zone", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - // Turn on SSL on our side - if (!stream_socket_enable_crypto($conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - throw new RODSException("Error turning on SSL on connection to server '$host:$port'."); - } - - // all good ... do the PAM authentication over the encrypted connection - $req_packet = new RP_pamAuthRequestInp($user, $pass, -1); - $msg=new RODSMessage("RODS_API_REQ_T", $req_packet, - $GLOBALS['PRODS_API_NUMS']['PAM_AUTH_REQUEST_AN']); - fwrite($conn, $msg->pack()); - $msg=new RODSMessage(); - $intInfo=$msg->unpack($conn); - if ($intInfo<0) - { - throw new RODSException("PAM auth failed at server '$host:$port' User: $user Zone: $zone", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - - // Update the account object with the temporary password - // and set the auth_type to irods for this connection - $pack = $msg->getBody(); - $pass = $this->account->pass = $pack->irodsPamPassword; - - // Done authentication ... turn ask the server to turn off SSL - $req_packet = new RP_sslEndInp(); - $msg=new RODSMessage("RODS_API_REQ_T", $req_packet, - $GLOBALS['PRODS_API_NUMS']['SSL_END_AN']); - fwrite($conn, $msg->pack()); - $msg=new RODSMessage(); - $intInfo=$msg->unpack($conn); - if ($intInfo<0) - { - throw new RODSException("Connection to '$host:$port' failed.ssl2. User: $user Zone: $zone", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - // De-activate SSL on the connection - stream_socket_enable_crypto($conn, false); - - // nasty hack ... some characters are left over to be read - // from the socket after the SSL shutdown, and I can't - // figure out how to consume them via SSL routines, so I - // just read them and throw them away. They need to be consumed - // or later reads get out of sync with the API responses - $r = array($conn); - $w = $e = null; - while (stream_select($r, $w, $e, 0) > 0) { - $s = fread($conn, 1); - } - - } - - // request authentication - $msg=new RODSMessage("RODS_API_REQ_T",NULL, - $GLOBALS['PRODS_API_NUMS']['AUTH_REQUEST_AN']); - fwrite($conn, $msg->pack()); - - // get chalange string - $msg=new RODSMessage(); - $intInfo=$msg->unpack($conn); - if ($intInfo<0) - { - throw new RODSException("Connection to '$host:$port' failed.3. User: $user Zone: $zone", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $pack=$msg->getBody(); - $challenge_b64encoded=$pack->challenge; - $challenge=base64_decode($challenge_b64encoded); - - // encode chalange with passwd - $pad_pass=str_pad($pass,MAX_PASSWORD_LEN,"\0"); - $pwmd5=md5($challenge.$pad_pass,true); - for ($i=0;$ipack()); - - // check if we are connected - // get chalange string - $msg=new RODSMessage(); - $intInfo=$msg->unpack($conn); - if ($intInfo<0) - { - $this->disconnect(); - throw new RODSException("Connection to '$host:$port' failed.4 (login failed, possible wrong user/passwd). User: $user Pass: $pass Zone: $zone", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - - $this->connected=true; - // use ticket if specified - if( !empty($this->account->ticket) ) { - $ticket_packet = new RP_ticketAdminInp('session', $this->account->ticket); - $msg = new RODSMessage('RODS_API_REQ_T', $ticket_packet, 723); - fwrite($conn, $msg->pack()); - - // get response - $msg = new RODSMessage(); - $intInfo = $msg->unpack($conn); - if ($intInfo < 0) { - $this->disconnect(); - throw new RODSException('Cannot set session ticket.', - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - } - /** - * Close the connection (socket) - */ - public function disconnect($force = false) - { - if (($this->connected === false) && ($force !== true)) - return; - - $msg = new RODSMessage("RODS_DISCONNECT_T"); - fwrite($this->conn, $msg->pack()); - fclose($this->conn); - $this->connected = false; - } - - public function createTicket( $object, $permission = 'read', $ticket = '' ) - { - if ($this->connected === false) { - throw new RODSException("createTicket needs an active connection, but the connection is currently inactive", - 'PERR_CONN_NOT_ACTIVE'); - } - if( empty($ticket) ) - { - // create a 16 characters long ticket - $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for ($i = 0; $i < 16; $i++) - $ticket .= $chars[mt_rand(1, strlen($chars))-1]; - } - - $ticket_packet = new RP_ticketAdminInp('create', $ticket, $permission, $object); - $msg = new RODSMessage('RODS_API_REQ_T', $ticket_packet, 723); - fwrite($this->conn, $msg->pack()); - - // get response - $msg = new RODSMessage(); - $intInfo = $msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException('Cannot create ticket "'.$ticket.'" for object "'.$object.'" with permission "'.$permission.'".', - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - - return $ticket; - } - - public function deleteTicket( $ticket ) - { - if ($this->connected === false) { - throw new RODSException("deleteTicket needs an active connection, but the connection is currently inactive", - 'PERR_CONN_NOT_ACTIVE'); - } - $ticket_packet = new RP_ticketAdminInp('delete', $ticket); - $msg = new RODSMessage('RODS_API_REQ_T', $ticket_packet, 723); - fwrite($this->conn, $msg->pack()); - - // get response - $msg = new RODSMessage(); - $intInfo = $msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException('Cannot delete ticket "'.$ticket.'".', - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * Get a temp password from the server. - * @param string $key key obtained from server to generate password. If this key is not specified, this function will ask server for a new key. - * @return string temp password - */ - public function getTempPassword($key = NULL) - { - if ($this->connected === false) { - throw new RODSException("getTempPassword needs an active connection, but the connection is currently inactive", - 'PERR_CONN_NOT_ACTIVE'); - } - if (NULL == $key) - $key = $this->getKeyForTempPassword(); - - $auth_str = str_pad($key . $this->account->pass, 100, "\0"); - $pwmd5 = bin2hex(md5($auth_str, true)); - - return $pwmd5; - } - - - /** - * Get a key for temp password from the server. this key can then be hashed together with real password to generate an temp password. - * @return string key for temp password - */ - public function getKeyForTempPassword() - { - if ($this->connected === false) { - throw new RODSException("getKeyForTempPassword needs an active connection, but the connection is currently inactive", - 'PERR_CONN_NOT_ACTIVE'); - } - $msg = new RODSMessage("RODS_API_REQ_T", null, - $GLOBALS['PRODS_API_NUMS']['GET_TEMP_PASSWORD_AN']); - - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::getKeyForTempPassword has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - return ($msg->getBody()->stringToHashWith); - } - - /** - * Get user information - * @param string username, if not specified, it will use current username instead - * @return array with fields: id, name, type, zone, dn, info, comment, ctime, mtime. If user not found return empty array. - */ - public function getUserInfo($user = NULL) - { - if (!isset($user)) - $user = $this->account->user; - - // set selected value - $select_val = array("COL_USER_ID", "COL_USER_NAME", "COL_USER_TYPE", - "COL_USER_ZONE", "COL_USER_DN", "COL_USER_INFO", - "COL_USER_COMMENT", "COL_USER_CREATE_TIME", "COL_USER_MODIFY_TIME"); - $cond = array(new RODSQueryCondition("COL_USER_NAME", $user)); - $que_result = $this->genQuery($select_val, $cond); - - if (false === $que_result) { - return array(); - } else { - $retval = array(); - $retval['id'] = $que_result["COL_USER_ID"][0]; - $retval['name'] = $que_result["COL_USER_NAME"][0]; - $retval['type'] = $que_result["COL_USER_TYPE"][0]; - // $retval['zone']=$que_result["COL_USER_ZONE"][0]; This can cause confusion if - // username is same as another federated grid - sometimes multiple records are returned. - // Changed source to force user to provide a zone until another method is suggested. - if ($this->account->zone == "") { - $retval['zone'] = $que_result["COL_USER_ZONE"][0]; - } else { - $retval['zone'] = $this->account->zone; - } - $retval['dn'] = $que_result["COL_USER_DN"][0]; - $retval['info'] = $que_result["COL_USER_INFO"][0]; - $retval['comment'] = $que_result["COL_USER_COMMENT"][0]; - $retval['ctime'] = $que_result["COL_USER_CREATE_TIME"][0]; - $retval['mtime'] = $que_result["COL_USER_MODIFY_TIME"][0]; - - return $retval; - } - } - - /** - * Make a new directory - * @param string $dir input direcotory path string - */ - public function mkdir($dir) - { - $collInp_pk = new RP_CollInp($dir); - $msg = new RODSMessage("RODS_API_REQ_T", $collInp_pk, - $GLOBALS['PRODS_API_NUMS']['COLL_CREATE_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME') { - throw new RODSException("Collection '$dir' Already exists!", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - throw new RODSException("RODSConn::mkdir has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * remove a directory - * @param string $dirpath input direcotory path string - * @param boolean $recursive whether recursively delete all child files and child directories recursively. - * @param boolean $force whether force delete the file/dir. If force delete, all files will be wiped physically. Else, they are moved to trash derectory. - * @param array $additional_flags An array of keyval pairs (array) reprenting additional flags passed to the server/client message. Each keyval pair is an array with first element repsenting the key, and second element representing the value (default to ''). Supported keys are: - * - 'irodsRmTrash' - whether this rm is a rmtrash operation - * - 'irodsAdminRmTrash' - whether this rm is a rmtrash operation done by admin user - * @param mixed $status_update_func It can be an string or array that represents the status update function (see http://us.php.net/manual/en/language.pseudo-types.php#language.types.callback), which can update status based on the server status update. Leave it blank or 'null' if there is no need to update the status. The function will be called with an assossive arry as parameter, supported fields are: - * - 'filesCnt' - finished number of files from previous update (normally 10 but not the last update) - * - 'lastObjPath' - last object that was processed. - * If this function returns 1, progress will be stopped. - */ - public function rmdir($dirpath, $recursive = true, $force = false, - $additional_flags = array(), $status_update_func = null) - { - $options = array(); - if ($force === true) { - $options["forceFlag"] = ""; - } - if ($recursive === true) { - $options["recursiveOpr"] = ""; - } - foreach ($additional_flags as $flagkey => $flagval) { - if (!empty($flagkey)) - $options[$flagkey] = $flagval; - } - $options_pk = new RP_KeyValPair(); - $options_pk->fromAssocArray($options); - - $collInp_pk = new RP_CollInp($dirpath, $options_pk); - $msg = new RODSMessage("RODS_API_REQ_T", $collInp_pk, - $GLOBALS['PRODS_API_NUMS']['RM_COLL_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - while ($msg->getBody() instanceof RP_CollOprStat) { - if (is_callable($status_update_func)) // call status update function if requested - { - $status = call_user_func($status_update_func, - array( - "filesCnt" => $msg->getBody()->filesCnt, - "lastObjPath" => $msg->getBody()->lastObjPath - ) - ); - if (false === $status) - throw new Exception("status_update_func failed!"); - else if (1 == $status) { - return; - } - } - - if ($intInfo == 0) //stop here if intinfo =0 (process completed) - break; - $this->replyStatusPacket(); - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - } - - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') { - return; - } - throw new RODSException("RODSConn::rmdir has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - // this is a temp work around for status packet reply. - // in status packet protocol, the server gives a status update packet: - // SYS_SVR_TO_CLI_COLL_STAT (99999996) - // and it expects an integer only SYS_CLI_TO_SVR_COLL_STAT_REPLY (99999997) - private function replyStatusPacket() - { - fwrite($this->conn, pack("N", 99999997)); - } - - /** - * Get children direcotories of input direcotory path string - * @param string $dir input direcotory path string - * @return an array of string, each string is the name of a child directory. This fuction return empty array, if there is no child direcotry found - */ - public function getChildDir($dir, $startingInx = 0, $maxresults = 500, - &$total_num_rows = -1) - { - $cond = array(new RODSQueryCondition("COL_COLL_PARENT_NAME", $dir)); - $que_result = $this->genQuery(array("COL_COLL_NAME"), $cond, array(), - $startingInx, $maxresults, true, array(), 0, $total_num_rows); - - if (false === $que_result) { - return array(); - } else { - if ($dir == "/") { - $result = array(); - foreach ($que_result["COL_COLL_NAME"] as $childdir) { - if ($childdir != "/") { - $result[] = $childdir; - } - } - return $result; - } - - return array_values($que_result["COL_COLL_NAME"]); - } - } - - /** - * Get children direcotories, with basic stats, of input direcotory path string - * @param string $dir input direcotory path string - * @param $orderby An associated array specifying how to sort the result by attributes. Each array key is the attribute, array val is 0 (assendent) or 1 (dessendent). The supported attributes are "name", "owner", "mtime". - * @return an array of RODSDirStats - */ - public function getChildDirWithStats($dir, $orderby = array(), $startingInx = 0, - $maxresults = 500, &$total_num_rows = -1) - { - // set selected value - $select_val = array("COL_COLL_NAME", "COL_COLL_ID", "COL_COLL_OWNER_NAME", - "COL_COLL_OWNER_ZONE", "COL_COLL_CREATE_TIME", "COL_COLL_MODIFY_TIME", - "COL_COLL_COMMENTS"); - $select_attr = array(); - - // set order by - if (!empty($orderby)) { - $select_attr = array_fill(0, count($select_val), 1); - foreach ($orderby as $key => $val) { - if ($key == "name") { - if ($val == 0) $select_attr[0] = ORDER_BY; - else $select_attr[0] = ORDER_BY_DESC; - } else - if ($key == "owner") { - if ($val == 0) $select_attr[2] = ORDER_BY; - else $select_attr[2] = ORDER_BY_DESC; - } else - if ($key == "mtime") { - if ($val == 0) $select_attr[5] = ORDER_BY; - else $select_attr[5] = ORDER_BY_DESC; - } - } - } - - $cond = array(new RODSQueryCondition("COL_COLL_PARENT_NAME", $dir)); - $continueInx = 0; - $que_result = $this->genQuery($select_val, $cond, - array(), $startingInx, $maxresults, true, - $select_attr, $continueInx, $total_num_rows); - - if (false === $que_result) { - return array(); - } else { - $ret_val = array(); - for ($i = 0; $i < count($que_result['COL_COLL_ID']); $i++) { - if ($que_result['COL_COLL_NAME'][$i] != "/") { - $ret_val[] = new RODSDirStats( - basename($que_result['COL_COLL_NAME'][$i]), - $que_result['COL_COLL_OWNER_NAME'][$i], - $que_result['COL_COLL_OWNER_ZONE'][$i], - $que_result['COL_COLL_MODIFY_TIME'][$i], - $que_result['COL_COLL_CREATE_TIME'][$i], - $que_result['COL_COLL_ID'][$i], - $que_result['COL_COLL_COMMENTS'][$i] - ); - } - } - return $ret_val; - } - } - - /** - * Get children file of input direcotory path string - * @param string $dir input direcotory path string - * @return an array of string, each string is the name of a child file. This fuction return empty array, if there is no child direcotry found. - */ - public function getChildFile($dir, $startingInx = 0, $maxresults = 500, - &$total_num_rows = -1) - { - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $dir)); - $que_result = $this->genQuery(array("COL_DATA_NAME"), $cond, array(), - $startingInx, $maxresults, true, array(), 0, $total_num_rows); - - if (false === $que_result) { - return array(); - } else { - return array_values($que_result["COL_DATA_NAME"]); - } - } - - /** - * Get children file, with basic stats, of input direcotory path string - * The stats - * @param string $dir input direcotory path string - * @param $orderby An associated array specifying how to sort the result by attributes. Each array key is the attribute, array val is 0 (assendent) or 1 (dessendent). The supported attributes are "name", "size", "owner", "mtime". - * @return an array of RODSFileStats - */ - public function getChildFileWithStats($dir, array $orderby = array(), - $startingInx = 0, $maxresults = 500, &$total_num_rows = -1) - { - // set selected value - $select_val = array("COL_DATA_NAME", "COL_D_DATA_ID", "COL_DATA_TYPE_NAME", - "COL_D_RESC_NAME", "COL_DATA_SIZE", "COL_D_OWNER_NAME", - "COL_D_CREATE_TIME", "COL_D_MODIFY_TIME"); - $select_attr = array(); - - // set order by - if (!empty($orderby)) { - $select_attr = array_fill(0, count($select_val), 1); - foreach ($orderby as $key => $val) { - if ($key == "name") { - if ($val == 0) $select_attr[0] = ORDER_BY; - else $select_attr[0] = ORDER_BY_DESC; - } else - if ($key == "size") { - if ($val == 0) $select_attr[4] = ORDER_BY; - else $select_attr[4] = ORDER_BY_DESC; - } else - if ($key == "owner") { - if ($val == 0) $select_attr[5] = ORDER_BY; - else $select_attr[5] = ORDER_BY_DESC; - } else - if ($key == "mtime") { - if ($val == 0) $select_attr[7] = ORDER_BY; - else $select_attr[7] = ORDER_BY_DESC; - } - } - } - - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $dir)); - $continueInx = 0; - $que_result = $this->genQuery($select_val, $cond, - array(), $startingInx, $maxresults, true, - $select_attr, $continueInx, $total_num_rows); - - - if (false === $que_result) { - return array(); - } else { - $ret_val = array(); - for ($i = 0; $i < count($que_result['COL_D_DATA_ID']); $i++) { - $ret_val[] = new RODSFileStats( - $que_result['COL_DATA_NAME'][$i], - $que_result['COL_DATA_SIZE'][$i], - $que_result['COL_D_OWNER_NAME'][$i], - $que_result['COL_D_MODIFY_TIME'][$i], - $que_result['COL_D_CREATE_TIME'][$i], - $que_result['COL_D_DATA_ID'][$i], - $que_result['COL_DATA_TYPE_NAME'][$i], - $que_result['COL_D_RESC_NAME'][$i] - ); - } - return $ret_val; - } - } - - /** - * Get basic stats, of input dir path string - * @param string $dirpath input dir path string - * @return RODSDirStats. If dir does not exists, return fales. - */ - public function getDirStats($dirpath) - { - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $dirpath)); - - $que_result = $this->genQuery( - array("COL_COLL_NAME", "COL_COLL_ID", "COL_COLL_OWNER_NAME", - "COL_COLL_OWNER_ZONE", "COL_COLL_CREATE_TIME", "COL_COLL_MODIFY_TIME", - "COL_COLL_COMMENTS"), - $cond, array(), 0, 1, false); - if ($que_result === false) return false; - - $stats = new RODSDirStats( - basename($que_result['COL_COLL_NAME'][0]), - $que_result['COL_COLL_OWNER_NAME'][0], - $que_result['COL_COLL_OWNER_ZONE'][0], - $que_result['COL_COLL_MODIFY_TIME'][0], - $que_result['COL_COLL_CREATE_TIME'][0], - $que_result['COL_COLL_ID'][0], - $que_result['COL_COLL_COMMENTS'][0] - ); - return $stats; - } - - /** - * Get basic stats, of input file path string - * @param string $filepath input file path string - * @return RODSFileStats. If file does not exists, return fales. - */ - public function getFileStats($filepath) - { - $parent = dirname($filepath); - $filename = basename($filepath); - - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $parent), - new RODSQueryCondition("COL_DATA_NAME", $filename)); - - $que_result = $this->genQuery( - array("COL_DATA_NAME", "COL_D_DATA_ID", "COL_DATA_TYPE_NAME", - "COL_D_RESC_NAME", "COL_DATA_SIZE", "COL_D_OWNER_NAME", "COL_D_OWNER_ZONE", - "COL_D_CREATE_TIME", - "COL_D_MODIFY_TIME", "COL_D_COMMENTS"), - $cond, array(), 0, 1, false); - if ($que_result === false) return false; - - $stats = new RODSFileStats( - $que_result['COL_DATA_NAME'][0], - $que_result['COL_DATA_SIZE'][0], - $que_result['COL_D_OWNER_NAME'][0], - $que_result['COL_D_OWNER_ZONE'][0], - $que_result['COL_D_MODIFY_TIME'][0], - $que_result['COL_D_CREATE_TIME'][0], - $que_result['COL_D_DATA_ID'][0], - $que_result['COL_DATA_TYPE_NAME'][0], - $que_result['COL_D_RESC_NAME'][0], - $que_result['COL_D_COMMENTS'][0]); - return $stats; - } - - /** - * Check whether a directory (in string) exists on RODS server. - * @return true/false - */ - public function dirExists($dir) - { - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $dir)); - $que_result = $this->genQuery(array("COL_COLL_ID"), $cond); - - if ($que_result === false) - return false; - else - return true; - } - - /** - * Check whether a file (in string) exists on RODS server. - * @return true/false - */ - public function fileExists($filepath, $rescname = NULL) - { - $parent = dirname($filepath); - $filename = basename($filepath); - if (empty($rescname)) { - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $parent), - new RODSQueryCondition("COL_DATA_NAME", $filename)); - $que_result = $this->genQuery(array("COL_D_DATA_ID"), $cond); - } else { - $cond = array(new RODSQueryCondition("COL_COLL_NAME", $parent), - new RODSQueryCondition("COL_DATA_NAME", $filename), - new RODSQueryCondition("COL_D_RESC_NAME", $rescname)); - $que_result = $this->genQuery(array("COL_D_DATA_ID"), $cond); - } - - if ($que_result === false) - return false; - else - return true; - } - - /** - * Replicate file to resources with options. - * @param string $path_src full path for the source file - * @param string $desc_resc destination resource - * @param array $options an assosive array of options: - * - 'all' (boolean): only meaningful if input resource is a resource group. Replicate to all the resources in the resource group. - * - 'backupMode' (boolean): if a good copy already exists in this resource, don't make another copy. - * - 'admin' (boolean): admin user uses this option to backup/replicate other users files - * - 'replNum' (integer): the replica to copy, typically not needed - * - 'srcResc' (string): specifies the source resource of the data object to be replicate, only copies stored in this resource will be replicated. Otherwise, one of the copy will be replicated - * These options are all 'optional', if omitted, the server will try to do it anyway - * @return number of bytes written if success, in case of faliure, throw an exception - */ - public function repl($path_src, $desc_resc, array $options = array()) - { - require_once(dirname(__FILE__) . "/RODSObjIOOpr.inc.php"); - require_once(dirname(__FILE__) . "/RodsGenQueryKeyWd.inc.php"); - - $optype = REPLICATE_OPR; - - $opt_arr = array(); - $opt_arr[$GLOBALS['PRODS_GENQUE_KEYWD']['DEST_RESC_NAME_KW']] = $desc_resc; - foreach ($options as $option_key => $option_val) { - switch ($option_key) { - case 'all': - if ($option_val === true) - $opt_arr[$GLOBALS['PRODS_GENQUE_KEYWD']['ALL_KW']] = ''; - break; - - case 'admin': - if ($option_val === true) - $opt_arr[$GLOBALS['PRODS_GENQUE_KEYWD']['IRODS_ADMIN_KW']] = ''; - break; - - case 'replNum': - $opt_arr[$GLOBALS['PRODS_GENQUE_KEYWD']['REPL_NUM_KW']] = $option_val; - break; - - case 'backupMode': - if ($option_val === true) - $opt_arr[$GLOBALS['PRODS_GENQUE_KEYWD'] - ['BACKUP_RESC_NAME_KW']] = $desc_resc; - break; - - default: - throw new RODSException("Option '$option_key'=>'$option_val' is not supported", - 'PERR_USER_INPUT_ERROR'); - } - } - - $keyvalpair = new RP_KeyValPair(); - $keyvalpair->fromAssocArray($opt_arr); - - $inp_pk = new RP_DataObjInp($path_src, 0, 0, 0, 0, 0, $optype, $keyvalpair); - - $msg = new RODSMessage("RODS_API_REQ_T", $inp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_REPL_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::repl has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - - $retpk = $msg->getBody(); - return $retpk->bytesWritten; - } - - /** - * Rename path_src to path_dest. - * @param string $path_src - * @param string $path_dest - * @param integer $path_type if 0, then path type is file, if 1, then path type if directory - * @return true/false - */ - public function rename($path_src, $path_dest, $path_type) - { - require_once(dirname(__FILE__) . "/RODSObjIOOpr.inc.php"); - - if ($path_type === 0) { - $path_type_magic_num = RENAME_DATA_OBJ; - } else { - $path_type_magic_num = RENAME_COLL; - } - $src_pk = new RP_DataObjInp($path_src, 0, 0, 0, 0, 0, $path_type_magic_num); - $dest_pk = new RP_DataObjInp($path_dest, 0, 0, 0, 0, 0, $path_type_magic_num); - $inp_pk = new RP_DataObjCopyInp($src_pk, $dest_pk); - $msg = new RODSMessage("RODS_API_REQ_T", $inp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_RENAME_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::rename has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * Open a file path (string) exists on RODS server. - * - * @param string $path file path - * @param string $mode open mode. Supported modes are: - * 'r' Open for reading only; place the file pointer at the beginning of the file. - * 'r+' Open for reading and writing; place the file pointer at the beginning of the file. - * 'w' Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it. - * 'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it. - * 'a' Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. - * 'a+' Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. - * 'x' Create and open for writing only; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. - * 'x+' Create and open for reading and writing; place the file pointer at the beginning of the file. If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. If the file does not exist, attempt to create it. This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. - * @param postion updated position - * @param string $rescname. Note that this parameter is required only if the file does not exists (create mode). If the file already exists, and if file resource is unknown or unique or you-dont-care for that file, leave the field, or pass NULL. - * @param boolean $assum_file_exists. This parameter specifies whether file exists. If the value is false, this mothod will check with RODS server to make sure. If value is true, the check will NOT be done. Default value is false. - * @param string $filetype. This parameter only make sense when you want to specify the file type, if file does not exists (create mode). If not specified, it defaults to "generic" - * @param integer $cmode. This parameter is only used for "createmode". It specifies the file mode on physical storage system (RODS vault), in octal 4 digit format. For instance, 0644 is owner readable/writeable, and nothing else. 0777 is all readable, writable, and excutable. If not specified, and the open flag requirs create mode, it defaults to 0644. - * @return integer level 1 descriptor - */ - public function openFileDesc($path, $mode, &$position, $rescname = NULL, - $assum_file_exists = false, $filetype = 'generic', $cmode = 0644) - { - $create_if_not_exists = false; - $error_if_exists = false; - $seek_to_end_of_file = false; - $position = 0; - - switch ($mode) { - case 'r': - $open_flag = O_RDONLY; - break; - case 'r+': - $open_flag = O_RDWR; - break; - case 'w': - $open_flag = O_WRONLY|O_TRUNC; - $create_if_not_exists = true; - break; - case 'w+': - $open_flag = O_RDWR|O_TRUNC; - $create_if_not_exists = true; - break; - case 'a': - $open_flag = O_WRONLY; - $create_if_not_exists = true; - $seek_to_end_of_file = true; - break; - case 'a+': - $open_flag = O_RDWR; - $create_if_not_exists = true; - $seek_to_end_of_file = true; - break; - case 'x': - $open_flag = O_WRONLY; - $create_if_not_exists = true; - $error_if_exists = true; - break; - case 'x+': - $open_flag = O_RDWR; - $create_if_not_exists = true; - $error_if_exists = true; - break; - default: - throw new RODSException("RODSConn::openFileDesc() does not recognize input mode:'$mode' ", - "PERR_USER_INPUT_ERROR"); - } - - if ($assum_file_exists === true) - $file_exists = true; - else - $file_exists = $this->fileExists($path, $rescname); - - if (($error_if_exists) && ($file_exists === true)) { - throw new RODSException("RODSConn::openFileDesc() expect file '$path' dose not exists with mode '$mode', but the file does exists", - "PERR_USER_INPUT_ERROR"); - } - - - if (($create_if_not_exists) && ($file_exists === false)) // create new file - { - $keyValPair_pk = new RP_KeyValPair(2, array("rescName", "dataType"), - array("$rescname", "$filetype")); - $dataObjInp_pk = new RP_DataObjInp($path, $cmode, $open_flag, 0, -1, 0, 0, - $keyValPair_pk); - $api_num = $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_CREATE_AN']; - } else // open existing file - { - // open the file and get descriptor - if (isset($rescname)) { - $keyValPair_pk = new RP_KeyValPair(1, array("rescName"), - array("$rescname")); - $dataObjInp_pk = new RP_DataObjInp - ($path, 0, $open_flag, 0, -1, 0, 0, $keyValPair_pk); - } else { - $dataObjInp_pk = new RP_DataObjInp - ($path, 0, $open_flag, 0, -1, 0, 0); - } - $api_num = $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_OPEN_AN']; - } - - $msg = new RODSMessage("RODS_API_REQ_T", $dataObjInp_pk, $api_num); - fwrite($this->conn, $msg->pack()); // send it - // get value back - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') { - throw new RODSException("trying to open a file '$path' " . - "which does not exists with mode '$mode' ", - "PERR_USER_INPUT_ERROR"); - } - throw new RODSException("RODSConn::openFileDesc has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $l1desc = $intInfo; - - if ($seek_to_end_of_file === true) { - $position = $this->fileSeek($l1desc, 0, SEEK_END); - } - - return $l1desc; - } - - /** - * unlink the file on server - * @param string $path path of the file - * @param string $rescname resource name. Not required if there is no other replica. - * @param boolean $force flag (true or false) indicating whether force delete or not. - * - */ - public function fileUnlink($path, $rescname = NULL, $force = false) - { - $options = array(); - if (isset($rescname)) { - $options['rescName'] = $rescname; - } - if ($force == true) { - $options['forceFlag'] = ""; - } - - if (!empty($options)) { - $options_pk = new RP_KeyValPair(); - $options_pk->fromAssocArray($options); - $dataObjInp_pk = new RP_DataObjInp - ($path, 0, 0, 0, -1, 0, 0, $options_pk); - } else { - $dataObjInp_pk = new RP_DataObjInp - ($path, 0, 0, 0, -1, 0, 0); - } - - $msg = new RODSMessage("RODS_API_REQ_T", $dataObjInp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_UNLINK_AN']); - fwrite($this->conn, $msg->pack()); // send it - // get value back - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') { - throw new RODSException("trying to unlink a file '$path' " . - "which does not exists", - "PERR_USER_INPUT_ERROR"); - } - throw new RODSException("RODSConn::fileUnlink has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * close the input file descriptor on RODS server. - * - * @param int $l1desc level 1 file descriptor - */ - public function closeFileDesc($l1desc) - { - try { - $dataObjCloseInp_pk = new RP_dataObjCloseInp($l1desc); - $msg = new RODSMessage("RODS_API_REQ_T", $dataObjCloseInp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_CLOSE_AN']); - fwrite($this->conn, $msg->pack()); // send it - // get value back - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - trigger_error("Got an error from server:$intInfo", - E_USER_WARNING); - } - } catch (RODSException $e) { - trigger_error("Got an exception:$e", E_USER_WARNING); - } - } - - /** - * reads up to length bytes from the file pointer referenced by handle. Reading stops when up to length bytes have been read, EOF (end of file) is reached - * - * @param int $l1desc level 1 file descriptor - * @param int $length up to how many bytes to read. - * @return the read string. - */ - public function fileRead($l1desc, $length) - { - $dataObjReadInp_pk = new RP_dataObjReadInp($l1desc, $length); - $msg = new RODSMessage("RODS_API_REQ_T", $dataObjReadInp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_READ_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::fileRead has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - return $msg->getBinstr(); - } - - /** - * writes up to length bytes from the file pointer referenced by handle. returns number of bytes writtne. - * - * @param int $l1desc level 1 file descriptor - * @param string $string contents (binary safe) to be written - * @param int $length up to how many bytes to read. - * @return the number of bytes written. - */ - public function fileWrite($l1desc, $string, $length = NULL) - { - if (!isset($length)) - $length = strlen($string); - - $dataObjWriteInp_pk = new RP_dataObjWriteInp($l1desc, $length); - $msg = new RODSMessage("RODS_API_REQ_T", $dataObjWriteInp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_WRITE_AN'], $string); - fwrite($this->conn, $msg->pack()); // send header and body msg - fwrite($this->conn, $string); // send contents - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::fileWrite has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - return $intInfo; - } - - /** - * Sets the file position indicator for the file referenced by l1desc (int descriptor). The new position, measured in bytes from the beginning of the file, is obtained by adding offset to the position specified by whence, whose values are defined as follows: - * SEEK_SET - Set position equal to offset bytes. - * SEEK_CUR - Set position to current location plus offset. - * SEEK_END - Set position to end-of-file plus offset. (To move to a position before the end-of-file, you need to pass a negative value in offset.) - * If whence is not specified, it is assumed to be SEEK_SET. - * @return int the current offset - */ - public function fileSeek($l1desc, $offset, $whence = SEEK_SET) - { - $dataObjReadInp_pk = new RP_fileLseekInp($l1desc, $offset, $whence); - $msg = new RODSMessage("RODS_API_REQ_T", $dataObjReadInp_pk, - $GLOBALS['PRODS_API_NUMS']['DATA_OBJ_LSEEK_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::fileSeek has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $retpk = $msg->getBody(); - return $retpk->offset; - } - - /** - * Get metadata for a file, dir, resource or user - * @param char $pathtype 'd'=file, 'c'=dir, 'r'=resource, 'u'=user - * @param string $name name of the target object. in the case of file and dir, use its full path - * @return RODSMeta $meta meta data for the target. - */ - public function getMeta($pathtype, $name) - { - switch ($pathtype) { - case 'd': - $select = array("COL_META_DATA_ATTR_NAME", "COL_META_DATA_ATTR_VALUE", - "COL_META_DATA_ATTR_UNITS", 'COL_META_DATA_ATTR_ID'); - $condition = array( - new RODSQueryCondition("COL_COLL_NAME", dirname($name)), - new RODSQueryCondition("COL_DATA_NAME", basename($name)) - ); - break; - case 'c': - $select = array("COL_META_COLL_ATTR_NAME", "COL_META_COLL_ATTR_VALUE", - "COL_META_COLL_ATTR_UNITS", 'COL_META_COLL_ATTR_ID'); - $condition = array(new RODSQueryCondition("COL_COLL_NAME", $name)); - break; - case 'r': - $select = array("COL_META_RESC_ATTR_NAME", "COL_META_RESC_ATTR_VALUE", - "COL_META_RESC_ATTR_UNITS", 'COL_META_RESC_ATTR_ID'); - $condition = array(new RODSQueryCondition("COL_R_RESC_NAME", $name)); - break; - case 'u': - $select = array("COL_META_USER_ATTR_NAME", "COL_META_USER_ATTR_VALUE", - "COL_META_USER_ATTR_UNITS", 'COL_META_USER_ATTR_ID'); - $condition = array(new RODSQueryCondition("COL_USER_NAME", $name)); - break; - default: - throw new RODSException("RODSConn::getMeta pathtype '$pathtype' is not supported!", - 'PERR_USER_INPUT_ERROR'); - } - - $genque_result = $this->genQuery($select, $condition); - - if ($genque_result === false) { - return array(); - } - $ret_array = array(); - for ($i = 0; $i < count($genque_result[$select[0]]); $i++) { - $ret_array[$i] = new RODSMeta( - $genque_result[$select[0]][$i], - $genque_result[$select[1]][$i], - $genque_result[$select[2]][$i], - $genque_result[$select[3]][$i] - ); - - } - return $ret_array; - - } - - /** - * Add metadata to a file, dir, resource or user - * @param char $pathtype 'd'=file, 'c'=dir, 'r'=resource, 'u'=user - * @param string $name name of the target object. in the case of file and dir, use its full path - * @param RODSMeta $meta meta data to be added. - */ - public function addMeta($pathtype, $name, RODSMeta $meta) - { - $pkt = new RP_ModAVUMetadataInp("add", "-$pathtype", $name, $meta->name, - $meta->value, $meta->units); - $msg = new RODSMessage("RODS_API_REQ_T", $pkt, - $GLOBALS['PRODS_API_NUMS']['MOD_AVU_METADATA_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::addMeta has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * remove metadata to a file, dir, resource or user - * @param char $pathtype 'd'=file, 'c'=dir, 'r'=resource, 'u'=user - * @param string $name name of the target object. in the case of file and dir, use its full path - * @param RODSMeta $meta meta data to be removed. - */ - public function rmMeta($pathtype, $name, RODSMeta $meta) - { - $pkt = new RP_ModAVUMetadataInp("rm", "-$pathtype", $name, $meta->name, - $meta->value, $meta->units); - $msg = new RODSMessage("RODS_API_REQ_T", $pkt, - $GLOBALS['PRODS_API_NUMS']['MOD_AVU_METADATA_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::rmMeta has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * remove metadata to a file, dir, resource or user - * @param char $pathtype 'd'=file, 'c'=dir, 'r'=resource, 'u'=user - * @param string $name name of the target object. in the case of file and dir, use its full path - * @param integer $metaid id of the metadata to be removed. - */ - public function rmMetaByID($pathtype, $name, $metaid) - { - $pkt = new RP_ModAVUMetadataInp("rmi", "-$pathtype", $name, $metaid); - $msg = new RODSMessage("RODS_API_REQ_T", $pkt, - $GLOBALS['PRODS_API_NUMS']['MOD_AVU_METADATA_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) != 'CAT_SUCCESS_BUT_WITH_NO_INFO') { - throw new RODSException("RODSConn::rmMetaByID has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - } - - /** - * copy metadata between file, dir, resource or user - * @param char $pathtype_src source path type 'd'=file, 'c'=dir, 'r'=resource, 'u'=user - * @param char $pathtype_dest destination path type 'd'=file, 'c'=dir, 'r'=resource, 'u'=user - * @param string $name_src name of the source target object. in the case of file and dir, use its full path - * @param string $name_dest name of the destination target object. in the case of file and dir, use its full path - */ - public function cpMeta($pathtype_src, $pathtype_dest, $name_src, $name_dest) - { - $pkt = new RP_ModAVUMetadataInp("cp", "-$pathtype_src", - "-$pathtype_dest", $name_src, $name_dest); - $msg = new RODSMessage("RODS_API_REQ_T", $pkt, - $GLOBALS['PRODS_API_NUMS']['MOD_AVU_METADATA_AN']); - fwrite($this->conn, $msg->pack()); // send it - $msg = new RODSMessage(); - $intInfo = (int)$msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::cpMeta has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - /** - * Excute a user defined rule - * @param string $rule_body body of the rule. Read this tutorial for details about rules: http://www.irods.org/index.php/Executing_user_defined_rules/workflow - * @param array $inp_params associative array defining input parameter for micro services used in this rule. only string and keyval pair are supported at this time. If the array value is a string, then type is string, if the array value is an RODSKeyValPair object, it will be treated a keyval pair - * @param array $out_params an array of names (strings) - * @param array $remotesvr if this rule need to run at remote server, this associative array should have the following keys: - * - 'host' remote host name or address - * - 'port' remote port - * - 'zone' remote zone - * if any of the value is empty, this option will be ignored. - * @param RODSKeyValPair $options an RODSKeyValPair specifying additional options, purpose of this is unknown at the developement time. Leave it alone if you are as clueless as me... - * @return an associative array. Each array key is the lable, and each array value's type will depend on the type of $out_param, at this moment, only string and RODSKeyValPair are supported - */ - public function execUserRule($rule_body, - array $inp_params = array(), array $out_params = array(), - array $remotesvr = array(), RODSKeyValPair $options = null) - { - $inp_params_packets = array(); - foreach ($inp_params as $inp_param_key => $inp_param_val) { - if (is_a($inp_param_val, 'RODSKeyValPair')) { - $inp_params_packets[] = new RP_MsParam($inp_param_key, - $inp_param_val->makePacket()); - } else // a string - { - $inp_params_packets[] = new RP_MsParam($inp_param_key, - new RP_STR($inp_param_val)); - } - } - $inp_param_arr_packet = new RP_MsParamArray($inp_params_packets); - - $out_params_desc = implode('%', $out_params); - - if ((isset($remotesvr['host'])) && (isset($remotesvr['port'])) && - (isset($remotesvr['zone'])) - ) { - $remotesvr_packet = new RP_RHostAddr($remotesvr['host'], - $remotesvr['zone'], $remotesvr['port']); - } else { - $remotesvr_packet = new RP_RHostAddr(); - } - - if (!isset($options)) - $options = new RODSKeyValPair(); - - $options_packet = $options->makePacket(); - - $pkt = new RP_ExecMyRuleInp($rule_body, $remotesvr_packet, - $options_packet, $out_params_desc, $inp_param_arr_packet); - $msg = new RODSMessage("RODS_API_REQ_T", $pkt, - $GLOBALS['PRODS_API_NUMS']['EXEC_MY_RULE_AN']); - fwrite($this->conn, $msg->pack()); // send it - $resv_msg = new RODSMessage(); - $intInfo = (int)$resv_msg->unpack($this->conn); - if ($intInfo < 0) { - throw new RODSException("RODSConn::execUserRule has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $retpk = $resv_msg->getBody(); - $param_array = $retpk->MsParam_PI; - $ret_arr = array(); - foreach ($param_array as $param) { - if ($param->type == 'STR_PI') { - $label = $param->label; - $ret_arr["$label"] = $param->STR_PI->myStr; - } else - if ($param->type == 'KeyValPair_PI') { - $label = $param->label; - $ret_arr["$label"] = RODSKeyValPair::fromPacket($param->KeyValPair_PI); - } else - if ($param->type == 'ExecCmdOut_PI') { - $label = $param->label; - $exec_ret_val = $param->ExecCmdOut_PI->buf; - $ret_arr["$label"] = $exec_ret_val; - } else { - throw new RODSException("RODSConn::execUserRule got. " . - "an unexpected output param with type: '$param->type' \n", - "PERR_UNEXPECTED_PACKET_FORMAT"); - } - } - return $ret_arr; - } - - /** - * This function is depreciated, and kept only for lagacy reasons! - * Makes a general query to RODS server. Think it as an SQL. "select foo from sometab where bar = '3'". In this example, foo is specified by "$select", bar and "= '3'" are speficed by condition. - * @param array $select the fields (names) to be returned/interested. There can not be more than 50 input fields. For example:"COL_COLL_NAME" means collection-name. - * @param array $condition Array of RODSQueryCondition. All fields are defined in RodsGenQueryNum.inc.php - * @param array $condition_kw Array of RODSQueryCondition. All fields are defined in RodsGenQueryKeyWd.inc.php - * @param integer $startingInx result start from which row. - * @param integer $maxresult up to how man rows should the result contain. - * @param boolean $getallrows whether to retreive all results - * @param boolean $select_attr attributes (array of int) of each select value. For instance, the attribute can be ORDER_BY (0x400) or ORDER_BY_DESC (0x800) to have the results sorted on the server. The default value is 1 for each attribute. Pass empty array or leave the option if you don't want anything fancy. - * @param integer $continueInx This index can be used to retrieve rest of results, when there is a overflow of the rows (> 500) - * @return an associated array, keys are the returning field names, each value is an array of the field values. Also, it returns false (boolean), if no rows are found. - * Note: This function is very low level. It's not recommended for beginners. - */ - public function genQuery(array $select, array $condition = array(), - array $condition_kw = array(), $startingInx = 0, $maxresults = 500, - $getallrows = true, array $select_attr = array(), &$continueInx = 0, - &$total_num_rows = -1) - { - if (count($select) > 50) { - trigger_error("genQuery(): Only upto 50 input are supported, rest ignored", - E_USER_WARNING); - $select = array_slice($select, 0, 50); - } - - $GenQueInp_options = 0; - if ($total_num_rows != -1) { - $GenQueInp_options = 1; - } - - require_once("RodsGenQueryNum.inc.php"); //load magic numbers - require_once("RodsGenQueryKeyWd.inc.php"); //load magic numbers - - // contruct select packet (RP_InxIvalPair $selectInp) - $select_pk = NULL; - if (count($select) > 0) { - if (empty($select_attr)) - $select_attr = array_fill(0, count($select), 1); - $idx = array(); - foreach ($select as $selval) { - if (isset($GLOBALS['PRODS_GENQUE_NUMS']["$selval"])) - $idx[] = $GLOBALS['PRODS_GENQUE_NUMS']["$selval"]; - else - trigger_error("genQuery(): select val '$selval' is not support, ignored", - E_USER_WARNING); - } - - $select_pk = new RP_InxIvalPair(count($select), $idx, $select_attr); - } else { - $select_pk = new RP_InxIvalPair(); - } - - foreach ($condition_kw as &$cond_kw) { - if (isset($GLOBALS['PRODS_GENQUE_KEYWD'][$cond_kw->name])) - $cond_kw->name = $GLOBALS['PRODS_GENQUE_KEYWD'][$cond_kw->name]; - } - - foreach ($condition as &$cond) { - if (isset($GLOBALS['PRODS_GENQUE_NUMS'][$cond->name])) - $cond->name = $GLOBALS['PRODS_GENQUE_NUMS'][$cond->name]; - } - - $condInput = new RP_KeyValPair(); - $condInput->fromRODSQueryConditionArray($condition_kw); - - $sqlCondInp = new RP_InxValPair(); - $sqlCondInp->fromRODSQueryConditionArray($condition); - - // construct RP_GenQueryInp packet - $genque_input_pk = new RP_GenQueryInp($maxresults, $continueInx, $condInput, - $select_pk, $sqlCondInp, $GenQueInp_options, $startingInx); - - // contruce a new API request message, with type GEN_QUERY_AN - $msg = new RODSMessage("RODS_API_REQ_T", $genque_input_pk, - $GLOBALS['PRODS_API_NUMS']['GEN_QUERY_AN']); - fwrite($this->conn, $msg->pack()); // send it - // get value back - $msg_resv = new RODSMessage(); - $intInfo = $msg_resv->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') { - return false; - } - - throw new RODSException("RODSConn::genQuery has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $genque_result_pk = $msg_resv->getBody(); - - $result_arr = array(); - for ($i = 0; $i < $genque_result_pk->attriCnt; $i++) { - $sql_res_pk = $genque_result_pk->SqlResult_PI[$i]; - $attri_name = $GLOBALS['PRODS_GENQUE_NUMS_REV'][$sql_res_pk->attriInx]; - $result_arr["$attri_name"] = $sql_res_pk->value; - } - if ($total_num_rows != -1) - $total_num_rows = $genque_result_pk->totalRowCount; - - - $more_results = true; - // if there are more results to be fetched - while (($genque_result_pk->continueInx > 0) && ($more_results === true) - && ($getallrows === true)) { - $msg->getBody()->continueInx = $genque_result_pk->continueInx; - fwrite($this->conn, $msg->pack()); // re-send it with new continueInx - // get value back - $msg_resv = new RODSMessage(); - $intInfo = $msg_resv->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') { - $more_results = false; - break; - } else - throw new RODSException("RODSConn::genQuery has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $genque_result_pk = $msg_resv->getBody(); - - for ($i = 0; $i < $genque_result_pk->attriCnt; $i++) { - $sql_res_pk = $genque_result_pk->SqlResult_PI[$i]; - $attri_name = $GLOBALS['PRODS_GENQUE_NUMS_REV'][$sql_res_pk->attriInx]; - $result_arr["$attri_name"] = - array_merge($result_arr["$attri_name"], $sql_res_pk->value); - } - } - - // Make sure and close the query if there are any results left. - if ($genque_result_pk->continueInx > 0) - { - $msg->getBody()->continueInx=$genque_result_pk->continueInx; - $msg->getBody()->maxRows=-1; // tells the server to close the query - fwrite($this->conn, $msg->pack()); - $msg_resv=new RODSMessage(); - $intInfo=$msg_resv->unpack($this->conn); - if ($intInfo<0) - { - throw new RODSException("RODSConn::genQuery has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - return $result_arr; - } - - /** - * Makes a general query to RODS server. Think it as an SQL. "select foo from sometab where bar = '3'". In this example, foo is specified by "$select", bar and "= '3'" are speficed by condition. - * @param RODSGenQueSelFlds $select the fields (names) to be returned/interested. There can not be more than 50 input fields. For example:"COL_COLL_NAME" means collection-name. - * @param RODSGenQueConds $condition All fields are defined in RodsGenQueryNum.inc.php and RodsGenQueryKeyWd.inc.php - * @param integer $start result start from which row. - * @param integer $limit up to how many rows should the result contain. If -1 is passed, all available rows will be returned - * @return RODSGenQueResults - * Note: This function is very low level. It's not recommended for beginners. - */ - public function query(RODSGenQueSelFlds $select, RODSGenQueConds $condition, - $start = 0, $limit = -1) - { - if (($select->getCount() < 1) || ($select->getCount() > 50)) { - throw new RODSException("Only 1-50 fields are supported", - 'PERR_USER_INPUT_ERROR'); - } - - // contruct select packet (RP_InxIvalPair $selectInp), and condition packets - $select_pk = $select->packetize(); - $cond_pk = $condition->packetize(); - $condkw_pk = $condition->packetizeKW(); - - // determin max number of results per query - if (($limit > 0) && ($limit < 500)) - $max_result_per_query = $limit; - else - $max_result_per_query = 500; - - $num_fetched_rows = 0; - $continueInx = 0; - $results = new RODSGenQueResults(); - do { - // construct RP_GenQueryInp packet - $options = 1 | $GLOBALS['PRODS_GENQUE_NUMS']['RETURN_TOTAL_ROW_COUNT']; - $genque_input_pk = new RP_GenQueryInp($max_result_per_query, - $continueInx, $condkw_pk, $select_pk, $cond_pk, $options, $start); - - // contruce a new API request message, with type GEN_QUERY_AN - $msg = new RODSMessage("RODS_API_REQ_T", $genque_input_pk, - $GLOBALS['PRODS_API_NUMS']['GEN_QUERY_AN']); - fwrite($this->conn, $msg->pack()); // send it - // get value back - $msg_resv = new RODSMessage(); - $intInfo = $msg_resv->unpack($this->conn); - if ($intInfo < 0) { - if (RODSException::rodsErrCodeToAbbr($intInfo) == 'CAT_NO_ROWS_FOUND') { - break; - } - - throw new RODSException("RODSConn::query has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - $genque_result_pk = $msg_resv->getBody(); - $num_row_added = $results->addResults($genque_result_pk); - $continueInx = $genque_result_pk->continueInx; - $start = $start + $results->getNumRow(); - } while (($continueInx > 0) && - (($results->getNumRow() < $limit) || ($limit < 0))); - - - // Make sure and close the query if there are any results left. - if ($continueInx > 0) - { - $msg->getBody()->continueInx=$continueInx; - $msg->getBody()->maxRows=-1; // tells the server to close the query - fwrite($this->conn, $msg->pack()); - $msg_resv=new RODSMessage(); - $intInfo=$msg_resv->unpack($this->conn); - if ($intInfo<0) - { - throw new RODSException("RODSConn::query has got an error from the server", - $GLOBALS['PRODS_ERR_CODES_REV']["$intInfo"]); - } - } - - return $results; - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSConnManager.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSConnManager.class.php deleted file mode 100644 index b3e8155da4..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSConnManager.class.php +++ /dev/null @@ -1,79 +0,0 @@ -waiting_queue = array(); - $this->conn_map = array(); - } - - public static function getConn(RODSAccount $account) - { - $manager = $GLOBALS['RODSConnManager']; - - $conn = new RODSConn($account); - $conn_sig = $conn->getSignature(); - if (!isset($manager->conn_map[$conn_sig])) - $manager->conn_map[$conn_sig] = array(); - - //check if there is any opened connection idle - foreach ($manager->conn_map[$conn_sig] as &$opened_conn) { - if ($opened_conn->isIdle()) { - //$opened_conn->lock(); - $account = $opened_conn->getAccount(); //update account if needed... - return $opened_conn; - } - } - - //check if there is any more new connection allowed - if (count($manager->conn_map[$conn_sig]) < MAX_NUM_CONN_PER_USER_SERVER) { - $conn->connect(); - $id = count($manager->conn_map[$conn_sig]); - $manager->conn_map[$conn_sig][$id] = $conn; - $conn->setId($id); - //$conn->lock(); - $account = $conn->getAccount(); //update account if needed... - return $conn; - } - - //because PHP doesn't support multithread, if we run out of connections, - //there is probably something went wrong. - throw new RODSException("Unexpectedly ran out of connections. Maybe some connections are not released??? ", - "PERR_INTERNAL_ERR"); - - //if no connection are available, sleep for 100ms and retry - usleep(100); - echo "i am sleeping...
\n"; - return RODSConnManager::getConn($account); - } - - public static function releaseConn(RODSConn $conn) - { - $manager = $GLOBALS['RODSConnManager']; - $conn_sig = $conn->getSignature(); - - //echo "id:".$conn->getId()." ".implode(",",array_keys($manager->conn_map[$conn_sig]))."
\n"; - - if (isset($manager->conn_map[$conn_sig][$conn->getId()])) { - $manager->conn_map[$conn_sig][$conn->getId()]->unlock(); - } - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSDirStats.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSDirStats.class.php deleted file mode 100644 index 16d24584f4..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSDirStats.class.php +++ /dev/null @@ -1,25 +0,0 @@ -name = $name; - $this->owner = $owner; - $this->ownerzone = $ownerzone; - $this->mtime = $mtime; - $this->ctime = $ctime; - $this->id = $id; - $this->comments = $comments; - } - -} - \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSException.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSException.class.php deleted file mode 100644 index 97116a102c..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSException.class.php +++ /dev/null @@ -1,182 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package Prods - */ - -$errtable_file = dirname(__FILE__) . "/RodsErrorTable.inc.php"; - -if (is_readable($errtable_file)) - require_once($errtable_file); -else - die("Could not read file $errtable_file
\n"); - -/** - * custom exception class for RODS - */ -class RODSException extends Exception -{ - private $code_abbr; - private $cause; - - /** - * Makes a new RODS excption - * @param string $message err/exception message - * @param string $code_abbr error code abbreviation - */ - public function __construct($message, $code_abbr = "UNKNOWN_PRODS_ERR", - Exception $cause = NULL) - { - $this->code_abbr = $code_abbr; - $this->cause = $cause; - - parent::__construct($message, $GLOBALS['PRODS_ERR_CODES'][$code_abbr]); - } - - public function getCause() - { - return $this->cause; - } - - public function getCodeAbbr() - { - return $this->code_abbr; - } - - public static function rodsErrCodeToAbbr($code) - { - if (isset($GLOBALS['PRODS_ERR_CODES_REV']["$code"])) - return $GLOBALS['PRODS_ERR_CODES_REV']["$code"]; - else - return null; - } - - public static function rodsErrAbbrToCode($codeabbr) - { - if (isset($GLOBALS['PRODS_ERR_CODES']["$codeabbr"])) - return $GLOBALS['PRODS_ERR_CODES']["$codeabbr"]; - else - return null; - } - - public function getStackTrace() - { - if ($this->cause !== null) { - $arr = array(); - $trace = $this->getTrace(); - array_push($arr, $trace[0]); - unset($trace); - if (get_class($this->cause) == "RODSException") { - foreach ($this->cause->getStackTrace() as $key => $trace) { - array_push($arr, $trace); - } - } else { - foreach ($this->cause->getTrace() as $key => $trace) { - array_push($arr, $trace); - } - } - return $arr; - } else { - return $this->getTrace(); - } - } - - public function showStackTrace() - { - $htmldoc = "

An exception was thrown :
"; - $htmldoc .= "Exception code : $this->code
"; - $htmldoc .= "Exception abbr : $this->code_abbr
"; - $htmldoc .= "Exception message : $this->message
"; - $htmldoc .= ""; - $i = 0; - foreach ($this->getStackTrace() as $key => $trace) { - $htmldoc .= $this->showTrace($trace, $i); - $i++; - } - $htmldoc .= "#$i {main}
"; - unset($i); - $htmldoc .= "

"; - return $htmldoc; - } - - private function showTrace($_trace, $_i) - { - $htmldoc = "#$_i "; - if (array_key_exists("file", $_trace)) { - $htmldoc .= $_trace["file"]; - } - if (array_key_exists("line", $_trace)) { - $htmldoc .= "(" . $_trace["line"] . "): "; - } - if (array_key_exists("class", $_trace) && array_key_exists("type", $_trace)) { - $htmldoc .= $_trace["class"] . $_trace["type"]; - } - if (array_key_exists("function", $_trace)) { - $htmldoc .= $_trace["function"] . "("; - if (array_key_exists("args", $_trace)) { - if (count($_trace["args"]) > 0) { - $args = $_trace["args"]; - $type = gettype($args[0]); - $value = $args[0]; - unset($args); - if ($type == "boolean") { - if ($value) { - $htmldoc .= "true"; - } else { - $htmldoc .= "false"; - } - } elseif ($type == "integer" || $type == "double") { - if (settype($value, "string")) { - if (strlen($value) <= 20) { - $htmldoc .= $value; - } else { - $htmldoc .= substr($value, 0, 17) . "..."; - } - } else { - if ($type == "integer") { - $htmldoc .= "? integer ?"; - } else { - $htmldoc .= "? double or float ?"; - } - } - } elseif ($type == "string") { - if (strlen($value) <= 18) { - $htmldoc .= "'$value'"; - } else { - $htmldoc .= "'" . substr($value, 0, 15) . "...'"; - } - } elseif ($type == "array") { - $htmldoc .= "Array"; - } elseif ($type == "object") { - $htmldoc .= "Object"; - } elseif ($type == "resource") { - $htmldoc .= "Resource"; - } elseif ($type == "NULL") { - $htmldoc .= "null"; - } elseif ($type == "unknown type") { - $htmldoc .= "? unknown type ?"; - } - unset($type); - unset($value); - } - if (count($_trace["args"]) > 1) { - $htmldoc .= ",..."; - } - } - $htmldoc .= ")
"; - } - return $htmldoc; - } - - /** - * Magic function to turn exception obj to a string - */ - public function __toString() - { - return __CLASS__ . ": [{$this->code} $this->code_abbr]: {$this->message}\n"; - //return $this->showStackTrace(); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSFileStats.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSFileStats.class.php deleted file mode 100644 index 6452c2b1e5..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSFileStats.class.php +++ /dev/null @@ -1,34 +0,0 @@ -name = $name; - $this->size = $size; - $this->owner = $owner; - $this->ownerzone = $ownerzone; - $this->mtime = $mtime; - $this->ctime = $ctime; - $this->id = $id; - $this->typename = $typename; - $this->rescname = $rescname; - $this->comments = $comments; - $this->num_replica = $num_replica; - } - -} - \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueConds.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueConds.class.php deleted file mode 100644 index 4bc10cc549..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueConds.class.php +++ /dev/null @@ -1,112 +0,0 @@ -=' and val='0', then the triplex means - * "foo >= 0" as one iRODS general query condition. - * @param array (of string) $names names of the field, which must be one defined in file 'RodsGenQueryNum.inc.php'. - * @param array (of string) $ops logical operator, such as '=' 'like' '>' - * @param array (of string) $vals value of the filed - */ - public function __construct(array $names = array(), array $ops = array(), - array $vals = array()) - { - require_once("RodsGenQueryNum.inc.php"); //load magic numbers - require_once("RodsGenQueryKeyWd.inc.php"); //load magic keywords - - $this->cond = array('names' => array(), 'sysnames' => array(), 'values' => array()); - $this->cond_kw = array('names' => array(), 'sysnames' => array(), 'values' => array()); - - for ($i = 0; $i < count($names); $i++) { - $name = $names[$i]; - $op = $ops[$i]; - $val = $vals[$i]; - if (isset($GLOBALS['PRODS_GENQUE_NUMS']["$name"])) { - $this->cond['names'][] = $name; - $this->cond['sysnames'][] = $GLOBALS['PRODS_GENQUE_NUMS']["$name"]; - $this->cond['values'][] = "$op '$val'"; - } else - if (isset($GLOBALS['PRODS_GENQUE_KEYWD']["$name"])) { - $this->cond_kw['names'][] = $name; - $this->cond_kw['sysnames'][] = $GLOBALS['PRODS_GENQUE_KEYWD']["$name"]; - $this->cond_kw['values'][] = "$op '$val'"; - } else { - throw new RODSException("General Query condition field name '$name' is not valid", - 'PERR_USER_INPUT_ERROR'); - } - } - } - - /** - * Add a single select field. - * @param string $name names of the field, which must be one defined in file 'RodsGenQueryNum.inc.php'. - * @param string $op logical operator, such as '=' 'like' '>' - * @param string $val value of the filed - * @param array an array of tuples of extra op's and val's, each tuple is an assosive array that has key 'op' and 'val'. These conditions will be 'OR' with the other conditions. - * for example add ('COL_D_DATA_ID','like', '/tempZone/home/rods/%', array(array('op'=>'=','val'=>'/tempZone/home/rods'"))) - * would select all file ids both in subdirectories under '/tempZone/home/rods' and directly under '/tempZone/home/rods' - */ - public function add($name, $op, $val, array $OR_ops_vals = array()) - { - require_once("RodsGenQueryNum.inc.php"); //load magic numbers - require_once("RodsGenQueryKeyWd.inc.php"); //load magic keywords - - if (isset($GLOBALS['PRODS_GENQUE_NUMS']["$name"])) { - $this->cond['names'][] = $name; - $this->cond['sysnames'][] = $GLOBALS['PRODS_GENQUE_NUMS']["$name"]; - $value = "$op '$val'"; - foreach ($OR_ops_vals as $op_val) { - $or_op = $op_val['op']; - $or_val = $op_val['val']; - if (empty($or_op) || empty($or_val)) - continue; - $value = $value . " || $or_op '$or_val'"; - } - $this->cond['values'][] = $value; - } else - if (isset($GLOBALS['PRODS_GENQUE_KEYWD']["$name"])) { - $this->cond_kw['names'][] = $name; - $this->cond_kw['sysnames'][] = $GLOBALS['PRODS_GENQUE_KEYWD']["$name"]; - $value = "$op '$val'"; - foreach ($OR_ops_vals as $op_val) { - $or_op = $op_val['op']; - $or_val = $op_val['val']; - if (empty($or_op) || empty($or_val)) - continue; - $value = $value . " || $or_op '$or_val'"; - } - $this->cond_kw['values'][] = $value; - } else { - throw new RODSException("General Query condition field name '$name' is not valid", - 'PERR_USER_INPUT_ERROR'); - } - } - - /** - * make a RP_InxValPair. - */ - public function packetize() - { - return (new RP_InxValPair(count($this->cond['names']), - $this->cond['sysnames'], $this->cond['values'])); - } - - /** - * make a RP_KeyValPair. - */ - public function packetizeKW() - { - return (new RP_KeyValPair(count($this->cond_kw['names']), - $this->cond_kw['sysnames'], $this->cond_kw['values'])); - } - - public function getCond() - { - return $this->cond; - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueResults.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueResults.class.php deleted file mode 100644 index 899b4f0e3b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueResults.class.php +++ /dev/null @@ -1,97 +0,0 @@ -total_count = $total_count; - $this->values = $result_array; - $this->numcol = count($result_array); - if ($this->numcol > 0) - $this->numrow = count(current($result_array)); - else - $this->numrow = 0; - } - - /** - * Add general query result packet RP_GenQueryOut, directly from the protocol level query, into the result structure. - * @param RP_GenQueryOut $genque_result_pk result packet directly from the protocol level query. - * @return number of rows just added - */ - public function addResults(RP_GenQueryOut $genque_result_pk) - { - if ($genque_result_pk->totalRowCount > $this->total_count) - $this->total_count = $genque_result_pk->totalRowCount; - - require_once("RodsGenQueryNum.inc.php"); //load magic numbers - - $num_row_added = 0; - for ($i = 0; $i < $genque_result_pk->attriCnt; $i++) { - $sql_res_pk = $genque_result_pk->SqlResult_PI[$i]; - $attri_name = $GLOBALS['PRODS_GENQUE_NUMS_REV'][$sql_res_pk->attriInx]; - if (empty($this->values["$attri_name"])) - $this->values["$attri_name"] = $sql_res_pk->value; - else - array_splice($this->values["$attri_name"], - count($this->values["$attri_name"]), 0, $sql_res_pk->value); - if ($i == 0) { - $num_row_added = count($sql_res_pk->value); - if ($num_row_added != (int)$genque_result_pk->rowCnt) { - throw new RODSException("Gen Query result packet num row mismatch. Expect: $genque_result_pk->rowCnt, got: $num_row_added", - 'PERR_UNEXPECTED_PACKET_FORMAT'); - } - } - } - - $this->numcol = count($this->values); - if ($this->numcol > 0) - $this->numrow = count(current($this->values)); - else - $this->numrow = 0; - - return $num_row_added; - } - - /** - * get result values in (2-d) array, each array key is the name - * used RODSGenQueSelFlds, such as COL_COLL_NAME - */ - public function getValues() - { - return $this->values; - } - - /** - * get total result count, including all the potential results not returned. - */ - public function getTotalCount() - { - return $this->total_count; - } - - /** - * get number of columns/fields of the results. - */ - public function getNumCol() - { - return $this->numcol; - } - - /** - * get number of rows of the results. - */ - public function getNumRow() - { - return $this->numrow; - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueSelFlds.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueSelFlds.class.php deleted file mode 100644 index aa391613d0..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSGenQueSelFlds.class.php +++ /dev/null @@ -1,158 +0,0 @@ -names = $names; - $this->attrs = array(); - $this->indexes = array(); - - for ($i = 0; $i < count($names); $i++) { - $name = $names[$i]; - if (!isset($GLOBALS['PRODS_GENQUE_NUMS']["$name"])) { - throw new RODSException("General Query select field name '$name' is not valid", - 'PERR_USER_INPUT_ERROR'); - } - $this->indexes[] = $GLOBALS['PRODS_GENQUE_NUMS']["$name"]; - $this->attrs[] = RODSGenQueSelFlds::attr2GenQueNumber($attrs[$i]); - } - - } - - /** - * Add a single select field. - * - * @param string name name of the field, which must be one defined in file 'RodsGenQueryNum.inc.php'. - */ - public function add($name, $attr = NULL) - { - require_once("RodsGenQueryNum.inc.php"); //load magic numbers - if (!isset($GLOBALS['PRODS_GENQUE_NUMS']["$name"])) { - throw new RODSException("General Query select field name '$name' is not valid", - 'PERR_USER_INPUT_ERROR'); - } - $this->indexes[] = $GLOBALS['PRODS_GENQUE_NUMS']["$name"]; - $this->names[] = $name; - $this->attrs[] = RODSGenQueSelFlds::attr2GenQueNumber($attr); - } - - /** - * update a single select field's attr/value. Note that if the value already exists, - * it will OR the bits. This is used when you want more than one type of operation - * for a select field, such as select_max and sort. - */ - public function update($name, $attr) - { - require_once("RodsGenQueryNum.inc.php"); //load magic numbers - if (!isset($GLOBALS['PRODS_GENQUE_NUMS']["$name"])) { - throw new RODSException("General Query select field name '$name' is not valid", - 'PERR_USER_INPUT_ERROR'); - } - - $newattr = RODSGenQueSelFlds::attr2GenQueNumber($attr); - for ($i = 0; $i < count($this->names); $i++) { - if ($this->names[$i] == $name) { - if ($this->attrs[$i] == 1) - $this->attrs[$i] = $newattr; - else - $this->attrs[$i] = $newattr | $this->attrs[$i]; - return; - } - } - $this->add($name, $attr); - } - - /** - * Convert supported attribute to magic number, that iRODS protocol uses - * Following attributes are supported: - * - 'order_by_asc' order the result by this field, in ASCENDING order - * - 'order_by_desc' order the result by this field, in DESCENDING order - * - min minimum of the group - * - max maximum of the group - * - sum sum of the group - * - avg average of the group - * - count count of the group - */ - public static function attr2GenQueNumber($attr) - { - if (empty($attr)) return 1; - $retval = 1; - switch ($attr) { - case 'order_by_asc': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['ORDER_BY']; - break; - case 'order_by_desc': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['ORDER_BY_DESC']; - break; - case 'min': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['SELECT_MIN']; - break; - case 'max': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['SELECT_MAX']; - break; - case 'sum': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['SELECT_SUM']; - break; - case 'avg': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['SELECT_AVG']; - break; - case 'count': - $retval = $GLOBALS['PRODS_GENQUE_NUMS']['SELECT_COUNT']; - break; - default: - throw new RODSException("Unexpected attribute: '$attr'", - 'PERR_USER_INPUT_ERROR'); - } - return intval($retval); - } - - /** - * make a RP_InxIvalPair, a low level iRODS packet - */ - public function packetize() - { - return (new RP_InxIvalPair(count($this->names), $this->indexes, - $this->attrs)); - - } - - public function getIndexes() - { - return $this->indexes; - } - - public function getAttrs() - { - return $this->attrs; - } - - public function getCount() - { - return count($this->names); - } - - public function getNames() - { - return $this->names; - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSKeyValPair.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSKeyValPair.class.php deleted file mode 100644 index f347f7c988..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSKeyValPair.class.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @copyright Copyright © 2007, TBD - * @package RODSConn - */ - - -require_once("autoload.inc.php"); - -class RODSKeyValPair -{ - private $keys; - private $vals; - - public function __construct(array $arr = array()) - { - $this->keys = array_keys($arr); - $this->vals = array_values($arr); - } - - public function addPair($key, $val) - { - $this->keys[] = $key; - $this->vals[] = $val; - } - - /** - * Make a RP_KeyValPair - * @return RP_KeyValPair a RP_KeyValPair object - */ - public function makePacket() - { - return new RP_KeyValPair(count($this->keys), $this->keys, $this->vals); - } - - /** - * make a RODSKeyValPair from a RP_KeyValPair - */ - public static function fromPacket(RP_KeyValPair $RP_KeyValPair) - { - $new_keyval = new RODSKeyValPair(); - $new_keyval->keys = $RP_KeyValPair->keyWord; - $new_keyval->vals = $RP_KeyValPair->svalue; - return $new_keyval; - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSMessage.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSMessage.class.php deleted file mode 100644 index 243903a42d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSMessage.class.php +++ /dev/null @@ -1,183 +0,0 @@ - "RODS_CONNECT", - "RODS_VERSION_T" => "RODS_VERSION", - "RODS_API_REQ_T" => "RODS_API_REQ", - "RODS_DISCONNECT_T" => "RODS_DISCONNECT", - "RODS_REAUTH_T" => "RODS_REAUTH", - "RODS_API_REPLY_T" => "RODS_API_REPLY" -); - -class RODSMessage -{ - private $type; // (String) message type, such as "RODS_CONNECT_T" - private $typestr; // (String) str representation of the type that RODS server understand - private $msg; // (RODSPacket) main message body - private $header; // (RODSPacket) a special packet, header for other packets - private $header_xml; // (string) packet header in XML - private $msg_xml; // (string) message in XML - private $binstr; // (string) binary string - private $errstr; // (string) error string - private $intinfo; // an additional integer info, for API, it is the - // apiReqNum - private $serialized; - - public function __construct($type = NULL, $_msg = NULL, $intinfo = 0, $binstr = "", $errstr = "") - { - if (!isset($type)) { - return; - } - - $this->type = $type; - $RODSMessage_types = $GLOBALS['RODSMessage_types']; - if (!isset($RODSMessage_types[$type])) { - throw new RODSException("RODSMessage::__construct failed.1! Unknown type '$type'", - "PERR_INTERNAL_ERR"); - } - $this->typestr = $RODSMessage_types[$type]; - - if (isset($_msg)) { - if (!($_msg instanceof RODSPacket)) { - throw new RODSException("RODSMessage::__construct failed.2!", - "PERR_INTERNAL_ERR"); - } - } - $this->msg = $_msg; - $this->intinfo = $intinfo; - $this->binstr = $binstr; - $this->errstr = $errstr; - } - - public function pack() - { - if (isset($this->msg)) - $this->msg_xml = $this->msg->toXML(); - - $this->header = new RP_MsgHeader($this->typestr, strlen($this->msg_xml), - strlen($this->errstr), strlen($this->binstr), $this->intinfo); - $header_xml = $this->header->toXML(); - $this->serialized = pack("N", strlen($header_xml)) . $header_xml . - $this->msg_xml; - return $this->serialized; - } - - - public function unpack($conn, &$bslen = NULL) - { - if (FALSE === ($chunk = stream_get_contents($conn, 4))) { - throw new RODSException("RODSMessage::unpack failed.0! ", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - - - $arr = unpack("Nlen", $chunk); - $header_len = $arr['len']; - if ((!is_int($header_len)) || ($header_len < 1) || ($header_len > 8192 - 4)) { - throw new RODSException("RODSMessage::unpack failed.1! The header length is unexpected: '$header_len'", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - - $this->header_xml = stream_get_contents($conn, $header_len); - $this->parseHeaderXML($this->header_xml); - $intInfo = $this->header->intInfo; - - // get main msg string - $msg_len = $this->header->msgLen; - $this->msg_xml = stream_get_contents($conn, $msg_len); - if ($msg_len != strlen($this->msg_xml)) { - throw new RODSException("RODSMessage::unpack failed.2! " . - "The body length is unexpected: " . strlen($this->msg_xml) . - " expecting: $msg_len", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - if ($msg_len > 0) { - $this->parseBodyXML($this->msg_xml); - } - - // get err string - $errlen = $this->header->errorLen; - $this->errstr = stream_get_contents($conn, $errlen); - if ($errlen != strlen($this->errstr)) { - throw new RODSException("RODSMessage::unpack failed.3! " . - "The err length is unexpected: " . strlen($this->errstr) . - " expecting: $errlen", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - - // get bin string - $bslen = $this->header->bsLen; - $this->binstr = stream_get_contents($conn, $bslen); - if ($bslen != strlen($this->binstr)) { - throw new RODSException("RODSMessage::unpack failed.4! " . - "The bin str length is unexpected: " . strlen($this->binstr) . - " expecting: $bslen", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - - return $this->header->intInfo; - } - - private function parseHeaderXML($xmlstr) - { - $xml = new SimpleXMLElement($xmlstr); - $name = $xml->getName(); - if ($name != "MsgHeader_PI") { - throw new RODSException("RODSMessage::parseHeaderXML failed! " . - "The XML header name is unexpected:$name " . - " expecting: MsgHeader_PI", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - $this->header = new RP_MsgHeader(); - $this->header->fromSXE($xml); - } - - private function parseBodyXML($xmlstr) - { - //try { - $xml = new SimpleXMLElement($xmlstr); - $name = $xml->getName(); - if (substr($name, -3, 3) != "_PI") { - throw new RODSException("RODSMessage::parseMainBodyXML failed! " . - "The XML node's name is unexpected:$name " . - " expecting some thing like xxx_PI", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - $rp_classname = "RP_" . substr($name, 0, strlen($name) - 3); - $this->msg = new $rp_classname(); - $this->msg->fromSXE($xml); - - /*} catch (Exception $e) { - throw new RODSException("RODSMessage::parseMainBodyXML failed! ". - "Mal formated XML in RODS message :". - $xmlstr, - "SYS_PACK_INSTRUCT_FORMAT_ERR",$e); - } - */ - } - - public function getBody() - { - return $this->msg; - } - - public function getBinstr() - { - return $this->binstr; - } - - public function getXML() - { - return $this->header_xml . "\n" . $this->msg_xml; - } - - public static function packConnectMsg($user, $zone, $relVersion = RODS_REL_VERSION, - $apiVersion = RODS_API_VERSION, $option = NULL) - { - $msgbody = new RP_StartupPack($user, $zone, $relVersion, $apiVersion . $option); - $rods_msg = new RODSMessage("RODS_CONNECT_T", $msgbody); - return $rods_msg->pack(); - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSMeta.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSMeta.class.php deleted file mode 100644 index 55d48af19d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSMeta.class.php +++ /dev/null @@ -1,21 +0,0 @@ -name = $name; - $this->value = $value; - $this->units = $units; - $this->id = $id; - $this->op = $op; - } - -} - \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RODSObjIOOpr.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/RODSObjIOOpr.inc.php deleted file mode 100644 index 1d367e900b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RODSObjIOOpr.inc.php +++ /dev/null @@ -1,19 +0,0 @@ -name = $name; - $this->value = $value; - $this->op = $op; - } - - public function __toString() - { - return "$this->name $this->op '$this->value'"; - } - -} - \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RodsAPINum.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/RodsAPINum.inc.php deleted file mode 100644 index 258dfcab39..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RodsAPINum.inc.php +++ /dev/null @@ -1,216 +0,0 @@ - '500', - 'FILE_OPEN_AN' => '501', - 'FILE_WRITE_AN' => '502', - 'FILE_CLOSE_AN' => '503', - 'FILE_LSEEK_AN' => '504', - 'FILE_READ_AN' => '505', - 'FILE_UNLINK_AN' => '506', - 'FILE_MKDIR_AN' => '507', - 'FILE_CHMOD_AN' => '508', - 'FILE_RMDIR_AN' => '509', - 'FILE_STAT_AN' => '510', - 'FILE_FSTAT_AN' => '511', - 'FILE_FSYNC_AN' => '512', - 'FILE_STAGE_AN' => '513', - 'FILE_GET_FS_FREE_SPACE_AN' => '514', - 'FILE_OPENDIR_AN' => '515', - 'FILE_CLOSEDIR_AN' => '516', - 'FILE_READDIR_AN' => '517', - 'FILE_PUT_AN' => '518', - 'FILE_GET_AN' => '519', - 'FILE_CHKSUM_AN' => '520', - 'CHK_N_V_PATH_PERM_AN' => '521', - 'FILE_RENAME_AN' => '522', - 'FILE_TRUNCATE_AN' => '523', - 'DATA_OBJ_CREATE_AN' => '601', - 'DATA_OBJ_OPEN_AN' => '602', - 'DATA_OBJ_READ_AN' => '603', - 'DATA_OBJ_WRITE_AN' => '604', - 'DATA_OBJ_CLOSE_AN' => '605', - 'DATA_OBJ_PUT_AN' => '606', - 'DATA_PUT_AN' => '607', - 'DATA_OBJ_GET_AN' => '608', - 'DATA_GET_AN' => '609', - 'DATA_OBJ_REPL_AN' => '610', - 'DATA_COPY_AN' => '611', - 'DATA_OBJ_LSEEK_AN' => '612', - 'DATA_OBJ_COPY_AN' => '613', - 'SIMPLE_QUERY_AN' => '614', - 'DATA_OBJ_UNLINK_AN' => '615', - 'COLL_CREATE_AN' => '616', - 'RM_COLL_OLD_AN' => '617', - 'REG_COLL_AN' => '618', - 'REG_DATA_OBJ_AN' => '619', - 'UNREG_DATA_OBJ_AN' => '620', - 'REG_REPLICA_AN' => '621', - 'MOD_DATA_OBJ_META_AN' => '622', - 'RULE_EXEC_SUBMIT_AN' => '623', - 'RULE_EXEC_DEL_AN' => '624', - 'EXEC_MY_RULE_AN' => '625', - 'OPR_COMPLETE_AN' => '626', - 'DATA_OBJ_RENAME_AN' => '627', - 'DATA_OBJ_RSYNC_AN' => '628', - 'DATA_OBJ_CHKSUM_AN' => '629', - 'PHY_PATH_REG_AN' => '630', - 'DATA_OBJ_PHYMV_AN' => '631', - 'DATA_OBJ_TRIM_AN' => '632', - 'OBJ_STAT_AN' => '633', - 'EXEC_CMD_AN' => '634', - 'SUB_STRUCT_FILE_CREATE_AN' => '635', - 'SUB_STRUCT_FILE_OPEN_AN' => '636', - 'SUB_STRUCT_FILE_READ_AN' => '637', - 'SUB_STRUCT_FILE_WRITE_AN' => '638', - 'SUB_STRUCT_FILE_CLOSE_AN' => '639', - 'SUB_STRUCT_FILE_UNLINK_AN' => '640', - 'SUB_STRUCT_FILE_STAT_AN' => '641', - 'SUB_STRUCT_FILE_FSTAT_AN' => '642', - 'SUB_STRUCT_FILE_LSEEK_AN' => '643', - 'SUB_STRUCT_FILE_RENAME_AN' => '644', - 'QUERY_SPEC_COLL_AN' => '645', - 'MOD_COLL_AN' => '646', - 'SUB_STRUCT_FILE_MKDIR_AN' => '647', - 'SUB_STRUCT_FILE_RMDIR_AN' => '648', - 'SUB_STRUCT_FILE_OPENDIR_AN' => '649', - 'SUB_STRUCT_FILE_READDIR_AN' => '650', - 'SUB_STRUCT_FILE_CLOSEDIR_AN' => '651', - 'DATA_OBJ_TRUNCATE_AN' => '652', - 'SUB_STRUCT_FILE_TRUNCATE_AN' => '653', - 'GET_XMSG_TICKET_AN' => '654', - 'SEND_XMSG_AN' => '655', - 'RCV_XMSG_AN' => '656', - 'SUB_STRUCT_FILE_GET_AN' => '657', - 'SUB_STRUCT_FILE_PUT_AN' => '658', - 'SYNC_MOUNTED_COLL_AN' => '659', - 'STRUCT_FILE_SYNC_AN' => '660', - 'CLOSE_COLLECTION_AN' => '661', - 'COLL_REPL_AN' => '662', - 'RM_COLL_AN' => '663', - 'GET_MISC_SVR_INFO_AN' => '700', - 'GENERAL_ADMIN_AN' => '701', - 'GEN_QUERY_AN' => '702', - 'AUTH_REQUEST_AN' => '703', - 'AUTH_RESPONSE_AN' => '704', - 'AUTH_CHECK_AN' => '705', - 'MOD_AVU_METADATA_AN' => '706', - 'MOD_ACCESS_CONTROL_AN' => '707', - 'RULE_EXEC_MOD_AN' => '708', - 'GET_TEMP_PASSWORD_AN' => '709', - 'GENERAL_UPDATE_AN' => '710', - 'GSI_AUTH_REQUEST_AN' => '711', - 'OPEN_COLLECTION_AN' => '712', - 'READ_COLLECTION_AN' => '713', - 'PAM_AUTH_REQUEST_AN' => '725', - 'SSL_START_AN' => '1100', - 'SSL_END_AN' => '1101', -); -$GLOBALS['PRODS_API_NUMS_REV'] = array( - '500' => 'FILE_CREATE_AN', - '501' => 'FILE_OPEN_AN', - '502' => 'FILE_WRITE_AN', - '503' => 'FILE_CLOSE_AN', - '504' => 'FILE_LSEEK_AN', - '505' => 'FILE_READ_AN', - '506' => 'FILE_UNLINK_AN', - '507' => 'FILE_MKDIR_AN', - '508' => 'FILE_CHMOD_AN', - '509' => 'FILE_RMDIR_AN', - '510' => 'FILE_STAT_AN', - '511' => 'FILE_FSTAT_AN', - '512' => 'FILE_FSYNC_AN', - '513' => 'FILE_STAGE_AN', - '514' => 'FILE_GET_FS_FREE_SPACE_AN', - '515' => 'FILE_OPENDIR_AN', - '516' => 'FILE_CLOSEDIR_AN', - '517' => 'FILE_READDIR_AN', - '518' => 'FILE_PUT_AN', - '519' => 'FILE_GET_AN', - '520' => 'FILE_CHKSUM_AN', - '521' => 'CHK_N_V_PATH_PERM_AN', - '522' => 'FILE_RENAME_AN', - '523' => 'FILE_TRUNCATE_AN', - '601' => 'DATA_OBJ_CREATE_AN', - '602' => 'DATA_OBJ_OPEN_AN', - '603' => 'DATA_OBJ_READ_AN', - '604' => 'DATA_OBJ_WRITE_AN', - '605' => 'DATA_OBJ_CLOSE_AN', - '606' => 'DATA_OBJ_PUT_AN', - '607' => 'DATA_PUT_AN', - '608' => 'DATA_OBJ_GET_AN', - '609' => 'DATA_GET_AN', - '610' => 'DATA_OBJ_REPL_AN', - '611' => 'DATA_COPY_AN', - '612' => 'DATA_OBJ_LSEEK_AN', - '613' => 'DATA_OBJ_COPY_AN', - '614' => 'SIMPLE_QUERY_AN', - '615' => 'DATA_OBJ_UNLINK_AN', - '616' => 'COLL_CREATE_AN', - '617' => 'RM_COLL_OLD_AN', - '618' => 'REG_COLL_AN', - '619' => 'REG_DATA_OBJ_AN', - '620' => 'UNREG_DATA_OBJ_AN', - '621' => 'REG_REPLICA_AN', - '622' => 'MOD_DATA_OBJ_META_AN', - '623' => 'RULE_EXEC_SUBMIT_AN', - '624' => 'RULE_EXEC_DEL_AN', - '625' => 'EXEC_MY_RULE_AN', - '626' => 'OPR_COMPLETE_AN', - '627' => 'DATA_OBJ_RENAME_AN', - '628' => 'DATA_OBJ_RSYNC_AN', - '629' => 'DATA_OBJ_CHKSUM_AN', - '630' => 'PHY_PATH_REG_AN', - '631' => 'DATA_OBJ_PHYMV_AN', - '632' => 'DATA_OBJ_TRIM_AN', - '633' => 'OBJ_STAT_AN', - '634' => 'EXEC_CMD_AN', - '635' => 'SUB_STRUCT_FILE_CREATE_AN', - '636' => 'SUB_STRUCT_FILE_OPEN_AN', - '637' => 'SUB_STRUCT_FILE_READ_AN', - '638' => 'SUB_STRUCT_FILE_WRITE_AN', - '639' => 'SUB_STRUCT_FILE_CLOSE_AN', - '640' => 'SUB_STRUCT_FILE_UNLINK_AN', - '641' => 'SUB_STRUCT_FILE_STAT_AN', - '642' => 'SUB_STRUCT_FILE_FSTAT_AN', - '643' => 'SUB_STRUCT_FILE_LSEEK_AN', - '644' => 'SUB_STRUCT_FILE_RENAME_AN', - '645' => 'QUERY_SPEC_COLL_AN', - '646' => 'MOD_COLL_AN', - '647' => 'SUB_STRUCT_FILE_MKDIR_AN', - '648' => 'SUB_STRUCT_FILE_RMDIR_AN', - '649' => 'SUB_STRUCT_FILE_OPENDIR_AN', - '650' => 'SUB_STRUCT_FILE_READDIR_AN', - '651' => 'SUB_STRUCT_FILE_CLOSEDIR_AN', - '652' => 'DATA_OBJ_TRUNCATE_AN', - '653' => 'SUB_STRUCT_FILE_TRUNCATE_AN', - '654' => 'GET_XMSG_TICKET_AN', - '655' => 'SEND_XMSG_AN', - '656' => 'RCV_XMSG_AN', - '657' => 'SUB_STRUCT_FILE_GET_AN', - '658' => 'SUB_STRUCT_FILE_PUT_AN', - '659' => 'SYNC_MOUNTED_COLL_AN', - '660' => 'STRUCT_FILE_SYNC_AN', - '661' => 'CLOSE_COLLECTION_AN', - '662' => 'COLL_REPL_AN', - '663' => 'RM_COLL_AN', - '700' => 'GET_MISC_SVR_INFO_AN', - '701' => 'GENERAL_ADMIN_AN', - '702' => 'GEN_QUERY_AN', - '703' => 'AUTH_REQUEST_AN', - '704' => 'AUTH_RESPONSE_AN', - '705' => 'AUTH_CHECK_AN', - '706' => 'MOD_AVU_METADATA_AN', - '707' => 'MOD_ACCESS_CONTROL_AN', - '708' => 'RULE_EXEC_MOD_AN', - '709' => 'GET_TEMP_PASSWORD_AN', - '710' => 'GENERAL_UPDATE_AN', - '711' => 'GSI_AUTH_REQUEST_AN', - '712' => 'OPEN_COLLECTION_AN', - '713' => 'READ_COLLECTION_AN', - '725' => 'PAM_AUTH_REQUEST_AN', - '1100' => 'SSL_START_AN', - '1101' => 'SSL_END_AN', -); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RodsConst.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/RodsConst.inc.php deleted file mode 100644 index ecc2f5c259..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RodsConst.inc.php +++ /dev/null @@ -1,6 +0,0 @@ - '-1000', - 'SYS_SOCK_BIND_ERR' => '-2000', - 'SYS_SOCK_ACCEPT_ERR' => '-3000', - 'SYS_HEADER_READ_LEN_ERR' => '-4000', - 'SYS_HEADER_WRITE_LEN_ERR' => '-5000', - 'SYS_HEADER_TPYE_LEN_ERR' => '-6000', - 'SYS_CAUGHT_SIGNAL' => '-7000', - 'SYS_GETSTARTUP_PACK_ERR' => '-8000', - 'SYS_EXCEED_CONNECT_CNT' => '-9000', - 'SYS_USER_NOT_ALLOWED_TO_CONN' => '-10000', - 'SYS_READ_MSG_BODY_INPUT_ERR' => '-11000', - 'SYS_UNMATCHED_API_NUM' => '-12000', - 'SYS_NO_API_PRIV' => '-13000', - 'SYS_API_INPUT_ERR' => '-14000', - 'SYS_PACK_INSTRUCT_FORMAT_ERR' => '-15000', - 'SYS_MALLOC_ERR' => '-16000', - 'SYS_GET_HOSTNAME_ERR' => '-17000', - 'SYS_OUT_OF_FILE_DESC' => '-18000', - 'SYS_FILE_DESC_OUT_OF_RANGE' => '-19000', - 'SYS_UNRECOGNIZED_REMOTE_FLAG' => '-20000', - 'SYS_INVALID_SERVER_HOST' => '-21000', - 'SYS_SVR_TO_SVR_CONNECT_FAILED' => '-22000', - 'SYS_BAD_FILE_DESCRIPTOR' => '-23000', - 'SYS_INTERNAL_NULL_INPUT_ERR' => '-24000', - 'SYS_CONFIG_FILE_ERR' => '-25000', - 'SYS_INVALID_ZONE_NAME' => '-26000', - 'SYS_COPY_LEN_ERR' => '-27000', - 'SYS_PORT_COOKIE_ERR' => '-28000', - 'SYS_KEY_VAL_TABLE_ERR' => '-29000', - 'SYS_INVALID_RESC_TYPE' => '-30000', - 'SYS_INVALID_FILE_PATH' => '-31000', - 'SYS_INVALID_RESC_INPUT' => '-32000', - 'SYS_INVALID_PORTAL_OPR' => '-33000', - 'SYS_PARA_OPR_NO_SUPPORT' => '-34000', - 'SYS_INVALID_OPR_TYPE' => '-35000', - 'SYS_NO_PATH_PERMISSION' => '-36000', - 'SYS_NO_ICAT_SERVER_ERR' => '-37000', - 'SYS_AGENT_INIT_ERR' => '-38000', - 'SYS_PROXYUSER_NO_PRIV' => '-39000', - 'SYS_NO_DATA_OBJ_PERMISSION' => '-40000', - 'SYS_DELETE_DISALLOWED' => '-41000', - 'SYS_OPEN_REI_FILE_ERR' => '-42000', - 'SYS_NO_RCAT_SERVER_ERR' => '-43000', - 'SYS_UNMATCH_PACK_INSTRUCTI_NAME' => '-44000', - 'SYS_SVR_TO_CLI_MSI_NO_EXIST' => '-45000', - 'SYS_COPY_ALREADY_IN_RESC' => '-46000', - 'SYS_RECONN_OPR_MISMATCH' => '-47000', - 'SYS_INPUT_PERM_OUT_OF_RANGE' => '-48000', - 'SYS_FORK_ERROR' => '-49000', - 'SYS_PIPE_ERROR' => '-50000', - 'SYS_EXEC_CMD_STATUS_SZ_ERROR' => '-51000', - 'SYS_PATH_IS_NOT_A_FILE' => '-52000', - 'SYS_UNMATCHED_SPEC_COLL_TYPE' => '-53000', - 'SYS_TOO_MANY_QUERY_RESULT' => '-54000', - 'USER_AUTH_SCHEME_ERR' => '-300000', - 'USER_AUTH_STRING_EMPTY' => '-301000', - 'USER_RODS_HOST_EMPTY' => '-302000', - 'USER_RODS_HOSTNAME_ERR' => '-303000', - 'USER_SOCK_OPEN_ERR' => '-304000', - 'USER_SOCK_CONNECT_ERR' => '-305000', - 'USER_STRLEN_TOOLONG' => '-306000', - 'USER_API_INPUT_ERR' => '-307000', - 'USER_PACKSTRUCT_INPUT_ERR' => '-308000', - 'USER_NO_SUPPORT_ERR' => '-309000', - 'USER_FILE_DOES_NOT_EXIST' => '-310000', - 'USER_FILE_TOO_LARGE' => '-311000', - 'OVERWITE_WITHOUT_FORCE_FLAG' => '-312000', - 'UNMATCHED_KEY_OR_INDEX' => '-313000', - 'USER_CHKSUM_MISMATCH' => '-314000', - 'USER_BAD_KEYWORD_ERR' => '-315000', - 'USER__NULL_INPUT_ERR' => '-316000', - 'USER_INPUT_PATH_ERR' => '-317000', - 'USER_INPUT_OPTION_ERR' => '-318000', - 'USER_INVALID_USERNAME_FORMAT' => '-319000', - 'USER_DIRECT_RESC_INPUT_ERR' => '-320000', - 'USER_NO_RESC_INPUT_ERR' => '-321000', - 'USER_PARAM_LABEL_ERR' => '-322000', - 'USER_PARAM_TYPE_ERR' => '-323000', - 'BASE64_BUFFER_OVERFLOW' => '-324000', - 'BASE64_INVALID_PACKET' => '-325000', - 'USER_MSG_TYPE_NO_SUPPORT' => '-326000', - 'USER_RSYNC_NO_MODE_INPUT_ERR' => '-337000', - 'USER_OPTION_INPUT_ERR' => '-338000', - 'SAME_SRC_DEST_PATHS_ERR' => '-339000', - 'USER_RESTART_FILE_INPUT_ERR' => '-340000', - 'RESTART_OPR_FAILED' => '-341000', - 'BAD_EXEC_CMD_PATH' => '-342000', - 'EXEC_CMD_OUTPUT_TOO_LARGE' => '-343000', - 'EXEC_CMD_ERROR' => '-344000', - 'FILE_INDEX_LOOKUP_ERR' => '-500000', - 'UNIX_FILE_OPEN_ERR' => '-510000', - 'UNIX_FILE_OPEN_ERR_1' => '-510001', - 'UNIX_FILE_OPEN_ERR_2' => '-510002', - 'UNIX_FILE_CREATE_ERR' => '-511000', - 'UNIX_FILE_READ_ERR' => '-512000', - 'UNIX_FILE_WRITE_ERR' => '-513000', - 'UNIX_FILE_CLOSE_ERR' => '-514000', - 'UNIX_FILE_UNLINK_ERR' => '-515000', - 'UNIX_FILE_STAT_ERR' => '-516000', - 'UNIX_FILE_FSTAT_ERR' => '-517000', - 'UNIX_FILE_LSEEK_ERR' => '-518000', - 'UNIX_FILE_FSYNC_ERR' => '-519000', - 'UNIX_FILE_MKDIR_ERR' => '-520000', - 'UNIX_FILE_RMDIR_ERR' => '-521000', - 'UNIX_FILE_OPENDIR_ERR' => '-522000', - 'UNIX_FILE_CLOSEDIR_ERR' => '-523000', - 'UNIX_FILE_READDIR_ERR' => '-524000', - 'UNIX_FILE_STAGE_ERR' => '-525000', - 'UNIX_FILE_GET_FS_FREESPACE_ERR' => '-526000', - 'UNIX_FILE_CHMOD_ERR' => '-527000', - 'UNIX_FILE_RENAME_ERR' => '-528000', - 'CATALOG_NOT_CONNECTED' => '-801000', - 'CAT_ENV_ERR' => '-802000', - 'CAT_CONNECT_ERR' => '-803000', - 'CAT_DISCONNECT_ERR' => '-804000', - 'CAT_CLOSE_ENV_ERR' => '-805000', - 'CAT_SQL_ERR' => '-806000', - 'CAT_GET_ROW_ERR' => '-807000', - 'CAT_NO_ROWS_FOUND' => '-808000', - 'CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME' => '-809000', - 'CAT_INVALID_RESOURCE_TYPE' => '-810000', - 'CAT_INVALID_RESOURCE_CLASS' => '-811000', - 'CAT_INVALID_RESOURCE_NET_ADDR' => '-812000', - 'CAT_INVALID_RESOURCE_VAULT_PATH' => '-813000', - 'CAT_UNKNOWN_COLLECTION' => '-814000', - 'CAT_INVALID_DATA_TYPE' => '-815000', - 'CAT_INVALID_ARGUMENT' => '-816000', - 'CAT_UNKNOWN_FILE' => '-817000', - 'CAT_NO_ACCESS_PERMISSION' => '-818000', - 'CAT_SUCCESS_BUT_WITH_NO_INFO' => '-819000', - 'CAT_INVALID_USER_TYPE' => '-820000', - 'CAT_COLLECTION_NOT_EMPTY' => '-821000', - 'CAT_TOO_MANY_TABLES' => '-822000', - 'CAT_UNKNOWN_TABLE' => '-823000', - 'CAT_NOT_OPEN' => '-824000', - 'CAT_FAILED_TO_LINK_TABLES' => '-825000', - 'CAT_INVALID_AUTHENTICATION' => '-826000', - 'CAT_INVALID_USER' => '-827000', - 'CAT_INVALID_ZONE' => '-828000', - 'CAT_INVALID_GROUP' => '-829000', - 'CAT_INSUFFICIENT_PRIVILEGE_LEVEL' => '-830000', - 'CAT_INVALID_RESOURCE' => '-831000', - 'CAT_INVALID_CLIENT_USER' => '-832000', - 'CAT_NAME_EXISTS_AS_COLLECTION' => '-833000', - 'CAT_NAME_EXISTS_AS_DATAOBJ' => '-834000', - 'CAT_RESOURCE_NOT_EMPTY' => '-835000', - 'CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION' => '-836000', - 'CAT_RECURSIVE_MOVE' => '-837000', - 'CAT_LAST_REPLICA' => '-838000', - 'CAT_OCI_ERROR' => '-839000', - 'CAT_PASSWORD_EXPIRED' => '-840000', - 'FILE_OPEN_ERR' => '-900000', - 'FILE_READ_ERR' => '-901000', - 'FILE_WRITE_ERR' => '-902000', - 'PASSWORD_EXCEEDS_MAX_SIZE' => '-903000', - 'ENVIRONMENT_VAR_HOME_NOT_DEFINED' => '-904000', - 'UNABLE_TO_STAT_FILE' => '-905000', - 'AUTH_FILE_NOT_ENCRYPTED' => '-906000', - 'AUTH_FILE_DOES_NOT_EXIST' => '-907000', - 'UNLINK_FAILED' => '-908000', - 'NO_PASSWORD_ENTERED' => '-909000', - 'OBJPATH_EMPTY_IN_STRUCT_ERR' => '-1000000', - 'RESCNAME_EMPTY_IN_STRUCT_ERR' => '-1001000', - 'DATATYPE_EMPTY_IN_STRUCT_ERR' => '-1002000', - 'DATASIZE_EMPTY_IN_STRUCT_ERR' => '-1003000', - 'CHKSUM_EMPTY_IN_STRUCT_ERR' => '-1004000', - 'VERSION_EMPTY_IN_STRUCT_ERR' => '-1005000', - 'FILEPATH_EMPTY_IN_STRUCT_ERR' => '-1006000', - 'REPLNUM_EMPTY_IN_STRUCT_ERR' => '-1007000', - 'REPLSTATUS_EMPTY_IN_STRUCT_ERR' => '-1008000', - 'DATAOWNER_EMPTY_IN_STRUCT_ERR' => '-1009000', - 'DATAOWNERZONE_EMPTY_IN_STRUCT_ERR' => '-1010000', - 'DATAEXPIRY_EMPTY_IN_STRUCT_ERR' => '-1011000', - 'DATACOMMENTS_EMPTY_IN_STRUCT_ERR' => '-1012000', - 'DATACREATE_EMPTY_IN_STRUCT_ERR' => '-1013000', - 'DATAMODIFY_EMPTY_IN_STRUCT_ERR' => '-1014000', - 'DATAACCESS_EMPTY_IN_STRUCT_ERR' => '-1015000', - 'DATAACCESSINX_EMPTY_IN_STRUCT_ERR' => '-1016000', - 'NO_RULE_FOUND_ERR' => '-1017000', - 'NO_MORE_RULES_ERR' => '-1018000', - 'UNMATCHED_ACTION_ERR' => '-1019000', - 'RULES_FILE_READ_ERROR' => '-1020000', - 'ACTION_ARG_COUNT_MISMATCH' => '-1021000', - 'MAX_NUM_OF_ARGS_IN_ACTION_EXCEEDED' => '-1022000', - 'UNKNOWN_PARAM_IN_RULE_ERR' => '-1023000', - 'DESTRESCNAME_EMPTY_IN_STRUCT_ERR' => '-1024000', - 'BACKUPRESCNAME_EMPTY_IN_STRUCT_ERR' => '-1025000', - 'DATAID_EMPTY_IN_STRUCT_ERR' => '-1026000', - 'COLLID_EMPTY_IN_STRUCT_ERR' => '-1027000', - 'RESCGROUPNAME_EMPTY_IN_STRUCT_ERR' => '-1028000', - 'STATUSSTRING_EMPTY_IN_STRUCT_ERR' => '-1029000', - 'DATAMAPID_EMPTY_IN_STRUCT_ERR' => '-1030000', - 'USERNAMECLIENT_EMPTY_IN_STRUCT_ERR' => '-1031000', - 'RODSZONECLIENT_EMPTY_IN_STRUCT_ERR' => '-1032000', - 'USERTYPECLIENT_EMPTY_IN_STRUCT_ERR' => '-1033000', - 'HOSTCLIENT_EMPTY_IN_STRUCT_ERR' => '-1034000', - 'AUTHSTRCLIENT_EMPTY_IN_STRUCT_ERR' => '-1035000', - 'USERAUTHSCHEMECLIENT_EMPTY_IN_STRUCT_ERR' => '-1036000', - 'USERINFOCLIENT_EMPTY_IN_STRUCT_ERR' => '-1037000', - 'USERCOMMENTCLIENT_EMPTY_IN_STRUCT_ERR' => '-1038000', - 'USERCREATECLIENT_EMPTY_IN_STRUCT_ERR' => '-1039000', - 'USERMODIFYCLIENT_EMPTY_IN_STRUCT_ERR' => '-1040000', - 'USERNAMEPROXY_EMPTY_IN_STRUCT_ERR' => '-1041000', - 'RODSZONEPROXY_EMPTY_IN_STRUCT_ERR' => '-1042000', - 'USERTYPEPROXY_EMPTY_IN_STRUCT_ERR' => '-1043000', - 'HOSTPROXY_EMPTY_IN_STRUCT_ERR' => '-1044000', - 'AUTHSTRPROXY_EMPTY_IN_STRUCT_ERR' => '-1045000', - 'USERAUTHSCHEMEPROXY_EMPTY_IN_STRUCT_ERR' => '-1046000', - 'USERINFOPROXY_EMPTY_IN_STRUCT_ERR' => '-1047000', - 'USERCOMMENTPROXY_EMPTY_IN_STRUCT_ERR' => '-1048000', - 'USERCREATEPROXY_EMPTY_IN_STRUCT_ERR' => '-1049000', - 'USERMODIFYPROXY_EMPTY_IN_STRUCT_ERR' => '-1050000', - 'COLLNAME_EMPTY_IN_STRUCT_ERR' => '-1051000', - 'COLLPARENTNAME_EMPTY_IN_STRUCT_ERR' => '-1052000', - 'COLLOWNERNAME_EMPTY_IN_STRUCT_ERR' => '-1053000', - 'COLLOWNERZONE_EMPTY_IN_STRUCT_ERR' => '-1054000', - 'COLLEXPIRY_EMPTY_IN_STRUCT_ERR' => '-1055000', - 'COLLCOMMENTS_EMPTY_IN_STRUCT_ERR' => '-1056000', - 'COLLCREATE_EMPTY_IN_STRUCT_ERR' => '-1057000', - 'COLLMODIFY_EMPTY_IN_STRUCT_ERR' => '-1058000', - 'COLLACCESS_EMPTY_IN_STRUCT_ERR' => '-1059000', - 'COLLACCESSINX_EMPTY_IN_STRUCT_ERR' => '-1060000', - 'COLLMAPID_EMPTY_IN_STRUCT_ERR' => '-1062000', - 'COLLINHERITANCE_EMPTY_IN_STRUCT_ERR' => '-1063000', - 'RESCZONE_EMPTY_IN_STRUCT_ERR' => '-1065000', - 'RESCLOC_EMPTY_IN_STRUCT_ERR' => '-1066000', - 'RESCTYPE_EMPTY_IN_STRUCT_ERR' => '-1067000', - 'RESCTYPEINX_EMPTY_IN_STRUCT_ERR' => '-1068000', - 'RESCCLASS_EMPTY_IN_STRUCT_ERR' => '-1069000', - 'RESCCLASSINX_EMPTY_IN_STRUCT_ERR' => '-1070000', - 'RESCVAULTPATH_EMPTY_IN_STRUCT_ERR' => '-1071000', - 'NUMOPEN_ORTS_EMPTY_IN_STRUCT_ERR' => '-1072000', - 'PARAOPR_EMPTY_IN_STRUCT_ERR' => '-1073000', - 'RESCID_EMPTY_IN_STRUCT_ERR' => '-1074000', - 'GATEWAYADDR_EMPTY_IN_STRUCT_ERR' => '-1075000', - 'RESCMAX_BJSIZE_EMPTY_IN_STRUCT_ERR' => '-1076000', - 'FREESPACE_EMPTY_IN_STRUCT_ERR' => '-1077000', - 'FREESPACETIME_EMPTY_IN_STRUCT_ERR' => '-1078000', - 'FREESPACETIMESTAMP_EMPTY_IN_STRUCT_ERR' => '-1079000', - 'RESCINFO_EMPTY_IN_STRUCT_ERR' => '-1080000', - 'RESCCOMMENTS_EMPTY_IN_STRUCT_ERR' => '-1081000', - 'RESCCREATE_EMPTY_IN_STRUCT_ERR' => '-1082000', - 'RESCMODIFY_EMPTY_IN_STRUCT_ERR' => '-1083000', - 'INPUT_ARG_NOT_WELL_FORMED_ERR' => '-1084000', - 'INPUT_ARG_OUT_OF_ARGC_RANGE_ERR' => '-1085000', - 'INSUFFICIENT_INPUT_ARG_ERR' => '-1086000', - 'INPUT_ARG_DOES_NOT_MATCH_ERR' => '-1087000', - 'RETRY_WITHOUT_RECOVERY_ERR' => '-1088000', - 'CUT_ACTION_PROCESSED_ERR' => '-1089000', - 'ACTION_FAILED_ERR' => '-1090000', - 'FAIL_ACTION_ENCOUNTERED_ERR' => '-1091000', - 'VARIABLE_NAME_TOO_LONG_ERR' => '-1092000', - 'UNKNOWN_VARIABLE_MAP_ERR' => '-1093000', - 'UNDEFINED_VARIABLE_MAP_ERR' => '-1094000', - 'NULL_VALUE_ERR' => '-1095000', - 'DVARMAP_FILE_READ_ERROR' => '-1096000', - 'NO_RULE_OR_MSI_FUNCTION_FOUND_ERR' => '-1097000', - 'FILE_CREATE_ERROR' => '-1098000', - 'FMAP_FILE_READ_ERROR' => '-1099000', - 'DATE_FORMAT_ERR' => '-1100000', - 'RULE_FAILED_ERR' => '-1101000', - 'NO_MICROSERVICE_FOUND_ERR' => '-1102000', - 'INVALID_REGEXP' => '-1103000', - 'INVALID_OBJECT_NAME' => '-1104000', - 'INVALID_OBJECT_TYPE' => '-1105000', - 'NO_VALUES_FOUND' => '-1106000', - 'NO_COLUMN_NAME_FOUND' => '-1107000', - 'SYS_NULL_INPUT' => '-99999996', - 'SYS_HANDLER_DONE_WITH_ERROR' => '-99999997', - 'SYS_HANDLER_DONE_NO_ERROR' => '-99999998', - 'SYS_NO_HANDLER_REPLY_MSG' => '-99999999', - 'GENERAL_PRODS_ERR' => '-3000000', - 'PERR_INTERNAL_ERR' => '-3100000', - 'PERR_UNEXPECTED_PACKET_FORMAT' => '-3101000', - 'PERR_PATH_DOES_NOT_EXISTS' => '-3102000', - 'PERR_UNSUPPORTED_PROTOCOL_SCHEME' => '-3103000', - 'PERR_USER_INPUT_ERROR' => '-3104000', - 'PERR_USER_INPUT_PATH_ERROR' => '-3105000', - 'PERR_CONN_NOT_ACTIVE' => '-3106000', - 'SSL_NOT_BUILT_INTO_CLIENT' => '-2100000', - 'SSL_NOT_BUILT_INTO_SERVER' => '-2101000', - 'SSL_INIT_ERROR' => '-2102000', - 'SSL_HANDSHAKE_ERROR' => '-2103000', - 'SSL_SHUTDOWN_ERROR' => '-2104000', - 'SSL_CERT_ERROR' => '-2105000', - 'PAM_AUTH_NOT_BUILT_INTO_CLIENT' => '-991000', - 'PAM_AUTH_NOT_BUILT_INTO_SERVER' => '-992000', - 'PAM_AUTH_PASSWORD_FAILED' => '-993000', - 'PAM_AUTH_PASSWORD_INVALID_TTL' => '-994000', -); -$GLOBALS['PRODS_ERR_CODES_REV'] = array( - '-1000' => 'SYS_SOCK_OPEN_ERR', - '-2000' => 'SYS_SOCK_BIND_ERR', - '-3000' => 'SYS_SOCK_ACCEPT_ERR', - '-4000' => 'SYS_HEADER_READ_LEN_ERR', - '-5000' => 'SYS_HEADER_WRITE_LEN_ERR', - '-6000' => 'SYS_HEADER_TPYE_LEN_ERR', - '-7000' => 'SYS_CAUGHT_SIGNAL', - '-8000' => 'SYS_GETSTARTUP_PACK_ERR', - '-9000' => 'SYS_EXCEED_CONNECT_CNT', - '-10000' => 'SYS_USER_NOT_ALLOWED_TO_CONN', - '-11000' => 'SYS_READ_MSG_BODY_INPUT_ERR', - '-12000' => 'SYS_UNMATCHED_API_NUM', - '-13000' => 'SYS_NO_API_PRIV', - '-14000' => 'SYS_API_INPUT_ERR', - '-15000' => 'SYS_PACK_INSTRUCT_FORMAT_ERR', - '-16000' => 'SYS_MALLOC_ERR', - '-17000' => 'SYS_GET_HOSTNAME_ERR', - '-18000' => 'SYS_OUT_OF_FILE_DESC', - '-19000' => 'SYS_FILE_DESC_OUT_OF_RANGE', - '-20000' => 'SYS_UNRECOGNIZED_REMOTE_FLAG', - '-21000' => 'SYS_INVALID_SERVER_HOST', - '-22000' => 'SYS_SVR_TO_SVR_CONNECT_FAILED', - '-23000' => 'SYS_BAD_FILE_DESCRIPTOR', - '-24000' => 'SYS_INTERNAL_NULL_INPUT_ERR', - '-25000' => 'SYS_CONFIG_FILE_ERR', - '-26000' => 'SYS_INVALID_ZONE_NAME', - '-27000' => 'SYS_COPY_LEN_ERR', - '-28000' => 'SYS_PORT_COOKIE_ERR', - '-29000' => 'SYS_KEY_VAL_TABLE_ERR', - '-30000' => 'SYS_INVALID_RESC_TYPE', - '-31000' => 'SYS_INVALID_FILE_PATH', - '-32000' => 'SYS_INVALID_RESC_INPUT', - '-33000' => 'SYS_INVALID_PORTAL_OPR', - '-34000' => 'SYS_PARA_OPR_NO_SUPPORT', - '-35000' => 'SYS_INVALID_OPR_TYPE', - '-36000' => 'SYS_NO_PATH_PERMISSION', - '-37000' => 'SYS_NO_ICAT_SERVER_ERR', - '-38000' => 'SYS_AGENT_INIT_ERR', - '-39000' => 'SYS_PROXYUSER_NO_PRIV', - '-40000' => 'SYS_NO_DATA_OBJ_PERMISSION', - '-41000' => 'SYS_DELETE_DISALLOWED', - '-42000' => 'SYS_OPEN_REI_FILE_ERR', - '-43000' => 'SYS_NO_RCAT_SERVER_ERR', - '-44000' => 'SYS_UNMATCH_PACK_INSTRUCTI_NAME', - '-45000' => 'SYS_SVR_TO_CLI_MSI_NO_EXIST', - '-46000' => 'SYS_COPY_ALREADY_IN_RESC', - '-47000' => 'SYS_RECONN_OPR_MISMATCH', - '-48000' => 'SYS_INPUT_PERM_OUT_OF_RANGE', - '-49000' => 'SYS_FORK_ERROR', - '-50000' => 'SYS_PIPE_ERROR', - '-51000' => 'SYS_EXEC_CMD_STATUS_SZ_ERROR', - '-52000' => 'SYS_PATH_IS_NOT_A_FILE', - '-53000' => 'SYS_UNMATCHED_SPEC_COLL_TYPE', - '-54000' => 'SYS_TOO_MANY_QUERY_RESULT', - '-300000' => 'USER_AUTH_SCHEME_ERR', - '-301000' => 'USER_AUTH_STRING_EMPTY', - '-302000' => 'USER_RODS_HOST_EMPTY', - '-303000' => 'USER_RODS_HOSTNAME_ERR', - '-304000' => 'USER_SOCK_OPEN_ERR', - '-305000' => 'USER_SOCK_CONNECT_ERR', - '-306000' => 'USER_STRLEN_TOOLONG', - '-307000' => 'USER_API_INPUT_ERR', - '-308000' => 'USER_PACKSTRUCT_INPUT_ERR', - '-309000' => 'USER_NO_SUPPORT_ERR', - '-310000' => 'USER_FILE_DOES_NOT_EXIST', - '-311000' => 'USER_FILE_TOO_LARGE', - '-312000' => 'OVERWITE_WITHOUT_FORCE_FLAG', - '-313000' => 'UNMATCHED_KEY_OR_INDEX', - '-314000' => 'USER_CHKSUM_MISMATCH', - '-315000' => 'USER_BAD_KEYWORD_ERR', - '-316000' => 'USER__NULL_INPUT_ERR', - '-317000' => 'USER_INPUT_PATH_ERR', - '-318000' => 'USER_INPUT_OPTION_ERR', - '-319000' => 'USER_INVALID_USERNAME_FORMAT', - '-320000' => 'USER_DIRECT_RESC_INPUT_ERR', - '-321000' => 'USER_NO_RESC_INPUT_ERR', - '-322000' => 'USER_PARAM_LABEL_ERR', - '-323000' => 'USER_PARAM_TYPE_ERR', - '-324000' => 'BASE64_BUFFER_OVERFLOW', - '-325000' => 'BASE64_INVALID_PACKET', - '-326000' => 'USER_MSG_TYPE_NO_SUPPORT', - '-337000' => 'USER_RSYNC_NO_MODE_INPUT_ERR', - '-338000' => 'USER_OPTION_INPUT_ERR', - '-339000' => 'SAME_SRC_DEST_PATHS_ERR', - '-340000' => 'USER_RESTART_FILE_INPUT_ERR', - '-341000' => 'RESTART_OPR_FAILED', - '-342000' => 'BAD_EXEC_CMD_PATH', - '-343000' => 'EXEC_CMD_OUTPUT_TOO_LARGE', - '-344000' => 'EXEC_CMD_ERROR', - '-500000' => 'FILE_INDEX_LOOKUP_ERR', - '-510000' => 'UNIX_FILE_OPEN_ERR', - '-510001' => 'UNIX_FILE_OPEN_ERR_1', - '-510002' => 'UNIX_FILE_OPEN_ERR_2', - '-511000' => 'UNIX_FILE_CREATE_ERR', - '-512000' => 'UNIX_FILE_READ_ERR', - '-513000' => 'UNIX_FILE_WRITE_ERR', - '-514000' => 'UNIX_FILE_CLOSE_ERR', - '-515000' => 'UNIX_FILE_UNLINK_ERR', - '-516000' => 'UNIX_FILE_STAT_ERR', - '-517000' => 'UNIX_FILE_FSTAT_ERR', - '-518000' => 'UNIX_FILE_LSEEK_ERR', - '-519000' => 'UNIX_FILE_FSYNC_ERR', - '-520000' => 'UNIX_FILE_MKDIR_ERR', - '-521000' => 'UNIX_FILE_RMDIR_ERR', - '-522000' => 'UNIX_FILE_OPENDIR_ERR', - '-523000' => 'UNIX_FILE_CLOSEDIR_ERR', - '-524000' => 'UNIX_FILE_READDIR_ERR', - '-525000' => 'UNIX_FILE_STAGE_ERR', - '-526000' => 'UNIX_FILE_GET_FS_FREESPACE_ERR', - '-527000' => 'UNIX_FILE_CHMOD_ERR', - '-528000' => 'UNIX_FILE_RENAME_ERR', - '-801000' => 'CATALOG_NOT_CONNECTED', - '-802000' => 'CAT_ENV_ERR', - '-803000' => 'CAT_CONNECT_ERR', - '-804000' => 'CAT_DISCONNECT_ERR', - '-805000' => 'CAT_CLOSE_ENV_ERR', - '-806000' => 'CAT_SQL_ERR', - '-807000' => 'CAT_GET_ROW_ERR', - '-808000' => 'CAT_NO_ROWS_FOUND', - '-809000' => 'CATALOG_ALREADY_HAS_ITEM_BY_THAT_NAME', - '-810000' => 'CAT_INVALID_RESOURCE_TYPE', - '-811000' => 'CAT_INVALID_RESOURCE_CLASS', - '-812000' => 'CAT_INVALID_RESOURCE_NET_ADDR', - '-813000' => 'CAT_INVALID_RESOURCE_VAULT_PATH', - '-814000' => 'CAT_UNKNOWN_COLLECTION', - '-815000' => 'CAT_INVALID_DATA_TYPE', - '-816000' => 'CAT_INVALID_ARGUMENT', - '-817000' => 'CAT_UNKNOWN_FILE', - '-818000' => 'CAT_NO_ACCESS_PERMISSION', - '-819000' => 'CAT_SUCCESS_BUT_WITH_NO_INFO', - '-820000' => 'CAT_INVALID_USER_TYPE', - '-821000' => 'CAT_COLLECTION_NOT_EMPTY', - '-822000' => 'CAT_TOO_MANY_TABLES', - '-823000' => 'CAT_UNKNOWN_TABLE', - '-824000' => 'CAT_NOT_OPEN', - '-825000' => 'CAT_FAILED_TO_LINK_TABLES', - '-826000' => 'CAT_INVALID_AUTHENTICATION', - '-827000' => 'CAT_INVALID_USER', - '-828000' => 'CAT_INVALID_ZONE', - '-829000' => 'CAT_INVALID_GROUP', - '-830000' => 'CAT_INSUFFICIENT_PRIVILEGE_LEVEL', - '-831000' => 'CAT_INVALID_RESOURCE', - '-832000' => 'CAT_INVALID_CLIENT_USER', - '-833000' => 'CAT_NAME_EXISTS_AS_COLLECTION', - '-834000' => 'CAT_NAME_EXISTS_AS_DATAOBJ', - '-835000' => 'CAT_RESOURCE_NOT_EMPTY', - '-836000' => 'CAT_NOT_A_DATAOBJ_AND_NOT_A_COLLECTION', - '-837000' => 'CAT_RECURSIVE_MOVE', - '-838000' => 'CAT_LAST_REPLICA', - '-839000' => 'CAT_OCI_ERROR', - '-840000' => 'CAT_PASSWORD_EXPIRED', - '-900000' => 'FILE_OPEN_ERR', - '-901000' => 'FILE_READ_ERR', - '-902000' => 'FILE_WRITE_ERR', - '-903000' => 'PASSWORD_EXCEEDS_MAX_SIZE', - '-904000' => 'ENVIRONMENT_VAR_HOME_NOT_DEFINED', - '-905000' => 'UNABLE_TO_STAT_FILE', - '-906000' => 'AUTH_FILE_NOT_ENCRYPTED', - '-907000' => 'AUTH_FILE_DOES_NOT_EXIST', - '-908000' => 'UNLINK_FAILED', - '-909000' => 'NO_PASSWORD_ENTERED', - '-1000000' => 'OBJPATH_EMPTY_IN_STRUCT_ERR', - '-1001000' => 'RESCNAME_EMPTY_IN_STRUCT_ERR', - '-1002000' => 'DATATYPE_EMPTY_IN_STRUCT_ERR', - '-1003000' => 'DATASIZE_EMPTY_IN_STRUCT_ERR', - '-1004000' => 'CHKSUM_EMPTY_IN_STRUCT_ERR', - '-1005000' => 'VERSION_EMPTY_IN_STRUCT_ERR', - '-1006000' => 'FILEPATH_EMPTY_IN_STRUCT_ERR', - '-1007000' => 'REPLNUM_EMPTY_IN_STRUCT_ERR', - '-1008000' => 'REPLSTATUS_EMPTY_IN_STRUCT_ERR', - '-1009000' => 'DATAOWNER_EMPTY_IN_STRUCT_ERR', - '-1010000' => 'DATAOWNERZONE_EMPTY_IN_STRUCT_ERR', - '-1011000' => 'DATAEXPIRY_EMPTY_IN_STRUCT_ERR', - '-1012000' => 'DATACOMMENTS_EMPTY_IN_STRUCT_ERR', - '-1013000' => 'DATACREATE_EMPTY_IN_STRUCT_ERR', - '-1014000' => 'DATAMODIFY_EMPTY_IN_STRUCT_ERR', - '-1015000' => 'DATAACCESS_EMPTY_IN_STRUCT_ERR', - '-1016000' => 'DATAACCESSINX_EMPTY_IN_STRUCT_ERR', - '-1017000' => 'NO_RULE_FOUND_ERR', - '-1018000' => 'NO_MORE_RULES_ERR', - '-1019000' => 'UNMATCHED_ACTION_ERR', - '-1020000' => 'RULES_FILE_READ_ERROR', - '-1021000' => 'ACTION_ARG_COUNT_MISMATCH', - '-1022000' => 'MAX_NUM_OF_ARGS_IN_ACTION_EXCEEDED', - '-1023000' => 'UNKNOWN_PARAM_IN_RULE_ERR', - '-1024000' => 'DESTRESCNAME_EMPTY_IN_STRUCT_ERR', - '-1025000' => 'BACKUPRESCNAME_EMPTY_IN_STRUCT_ERR', - '-1026000' => 'DATAID_EMPTY_IN_STRUCT_ERR', - '-1027000' => 'COLLID_EMPTY_IN_STRUCT_ERR', - '-1028000' => 'RESCGROUPNAME_EMPTY_IN_STRUCT_ERR', - '-1029000' => 'STATUSSTRING_EMPTY_IN_STRUCT_ERR', - '-1030000' => 'DATAMAPID_EMPTY_IN_STRUCT_ERR', - '-1031000' => 'USERNAMECLIENT_EMPTY_IN_STRUCT_ERR', - '-1032000' => 'RODSZONECLIENT_EMPTY_IN_STRUCT_ERR', - '-1033000' => 'USERTYPECLIENT_EMPTY_IN_STRUCT_ERR', - '-1034000' => 'HOSTCLIENT_EMPTY_IN_STRUCT_ERR', - '-1035000' => 'AUTHSTRCLIENT_EMPTY_IN_STRUCT_ERR', - '-1036000' => 'USERAUTHSCHEMECLIENT_EMPTY_IN_STRUCT_ERR', - '-1037000' => 'USERINFOCLIENT_EMPTY_IN_STRUCT_ERR', - '-1038000' => 'USERCOMMENTCLIENT_EMPTY_IN_STRUCT_ERR', - '-1039000' => 'USERCREATECLIENT_EMPTY_IN_STRUCT_ERR', - '-1040000' => 'USERMODIFYCLIENT_EMPTY_IN_STRUCT_ERR', - '-1041000' => 'USERNAMEPROXY_EMPTY_IN_STRUCT_ERR', - '-1042000' => 'RODSZONEPROXY_EMPTY_IN_STRUCT_ERR', - '-1043000' => 'USERTYPEPROXY_EMPTY_IN_STRUCT_ERR', - '-1044000' => 'HOSTPROXY_EMPTY_IN_STRUCT_ERR', - '-1045000' => 'AUTHSTRPROXY_EMPTY_IN_STRUCT_ERR', - '-1046000' => 'USERAUTHSCHEMEPROXY_EMPTY_IN_STRUCT_ERR', - '-1047000' => 'USERINFOPROXY_EMPTY_IN_STRUCT_ERR', - '-1048000' => 'USERCOMMENTPROXY_EMPTY_IN_STRUCT_ERR', - '-1049000' => 'USERCREATEPROXY_EMPTY_IN_STRUCT_ERR', - '-1050000' => 'USERMODIFYPROXY_EMPTY_IN_STRUCT_ERR', - '-1051000' => 'COLLNAME_EMPTY_IN_STRUCT_ERR', - '-1052000' => 'COLLPARENTNAME_EMPTY_IN_STRUCT_ERR', - '-1053000' => 'COLLOWNERNAME_EMPTY_IN_STRUCT_ERR', - '-1054000' => 'COLLOWNERZONE_EMPTY_IN_STRUCT_ERR', - '-1055000' => 'COLLEXPIRY_EMPTY_IN_STRUCT_ERR', - '-1056000' => 'COLLCOMMENTS_EMPTY_IN_STRUCT_ERR', - '-1057000' => 'COLLCREATE_EMPTY_IN_STRUCT_ERR', - '-1058000' => 'COLLMODIFY_EMPTY_IN_STRUCT_ERR', - '-1059000' => 'COLLACCESS_EMPTY_IN_STRUCT_ERR', - '-1060000' => 'COLLACCESSINX_EMPTY_IN_STRUCT_ERR', - '-1062000' => 'COLLMAPID_EMPTY_IN_STRUCT_ERR', - '-1063000' => 'COLLINHERITANCE_EMPTY_IN_STRUCT_ERR', - '-1065000' => 'RESCZONE_EMPTY_IN_STRUCT_ERR', - '-1066000' => 'RESCLOC_EMPTY_IN_STRUCT_ERR', - '-1067000' => 'RESCTYPE_EMPTY_IN_STRUCT_ERR', - '-1068000' => 'RESCTYPEINX_EMPTY_IN_STRUCT_ERR', - '-1069000' => 'RESCCLASS_EMPTY_IN_STRUCT_ERR', - '-1070000' => 'RESCCLASSINX_EMPTY_IN_STRUCT_ERR', - '-1071000' => 'RESCVAULTPATH_EMPTY_IN_STRUCT_ERR', - '-1072000' => 'NUMOPEN_ORTS_EMPTY_IN_STRUCT_ERR', - '-1073000' => 'PARAOPR_EMPTY_IN_STRUCT_ERR', - '-1074000' => 'RESCID_EMPTY_IN_STRUCT_ERR', - '-1075000' => 'GATEWAYADDR_EMPTY_IN_STRUCT_ERR', - '-1076000' => 'RESCMAX_BJSIZE_EMPTY_IN_STRUCT_ERR', - '-1077000' => 'FREESPACE_EMPTY_IN_STRUCT_ERR', - '-1078000' => 'FREESPACETIME_EMPTY_IN_STRUCT_ERR', - '-1079000' => 'FREESPACETIMESTAMP_EMPTY_IN_STRUCT_ERR', - '-1080000' => 'RESCINFO_EMPTY_IN_STRUCT_ERR', - '-1081000' => 'RESCCOMMENTS_EMPTY_IN_STRUCT_ERR', - '-1082000' => 'RESCCREATE_EMPTY_IN_STRUCT_ERR', - '-1083000' => 'RESCMODIFY_EMPTY_IN_STRUCT_ERR', - '-1084000' => 'INPUT_ARG_NOT_WELL_FORMED_ERR', - '-1085000' => 'INPUT_ARG_OUT_OF_ARGC_RANGE_ERR', - '-1086000' => 'INSUFFICIENT_INPUT_ARG_ERR', - '-1087000' => 'INPUT_ARG_DOES_NOT_MATCH_ERR', - '-1088000' => 'RETRY_WITHOUT_RECOVERY_ERR', - '-1089000' => 'CUT_ACTION_PROCESSED_ERR', - '-1090000' => 'ACTION_FAILED_ERR', - '-1091000' => 'FAIL_ACTION_ENCOUNTERED_ERR', - '-1092000' => 'VARIABLE_NAME_TOO_LONG_ERR', - '-1093000' => 'UNKNOWN_VARIABLE_MAP_ERR', - '-1094000' => 'UNDEFINED_VARIABLE_MAP_ERR', - '-1095000' => 'NULL_VALUE_ERR', - '-1096000' => 'DVARMAP_FILE_READ_ERROR', - '-1097000' => 'NO_RULE_OR_MSI_FUNCTION_FOUND_ERR', - '-1098000' => 'FILE_CREATE_ERROR', - '-1099000' => 'FMAP_FILE_READ_ERROR', - '-1100000' => 'DATE_FORMAT_ERR', - '-1101000' => 'RULE_FAILED_ERR', - '-1102000' => 'NO_MICROSERVICE_FOUND_ERR', - '-1103000' => 'INVALID_REGEXP', - '-1104000' => 'INVALID_OBJECT_NAME', - '-1105000' => 'INVALID_OBJECT_TYPE', - '-1106000' => 'NO_VALUES_FOUND', - '-1107000' => 'NO_COLUMN_NAME_FOUND', - '-99999996' => 'SYS_NULL_INPUT', - '-99999997' => 'SYS_HANDLER_DONE_WITH_ERROR', - '-99999998' => 'SYS_HANDLER_DONE_NO_ERROR', - '-99999999' => 'SYS_NO_HANDLER_REPLY_MSG', - '-3000000' => 'GENERAL_PRODS_ERR', - '-3100000' => 'PERR_INTERNAL_ERR', - '-3101000' => 'PERR_UNEXPECTED_PACKET_FORMAT', - '-3102000' => 'PERR_PATH_DOES_NOT_EXISTS', - '-3103000' => 'PERR_UNSUPPORTED_PROTOCOL_SCHEME', - '-3104000' => 'PERR_USER_INPUT_ERROR', - '-3105000' => 'PERR_USER_INPUT_PATH_ERROR', - '-3106000' => 'PERR_CONN_NOT_ACTIVE', - '-2100000' => 'SSL_NOT_BUILT_INTO_CLIENT', - '-2101000' => 'SSL_NOT_BUILT_INTO_SERVER', - '-2102000' => 'SSL_INIT_ERROR', - '-2103000' => 'SSL_HANDSHAKE_ERROR', - '-2104000' => 'SSL_SHUTDOWN_ERROR', - '-2105000' => 'SSL_CERT_ERROR', - '-991000' => 'PAM_AUTH_NOT_BUILT_INTO_CLIENT', - '-992000' => 'PAM_AUTH_NOT_BUILT_INTO_SERVER', - '-993000' => 'PAM_AUTH_PASSWORD_FAILED', - '-994000' => 'PAM_AUTH_PASSWORD_INVALID_TTL', -); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RodsGenQueryKeyWd.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/RodsGenQueryKeyWd.inc.php deleted file mode 100644 index 55ad02e3b8..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RodsGenQueryKeyWd.inc.php +++ /dev/null @@ -1,224 +0,0 @@ - "all", - 'COPIES_KW' => "copies", - 'EXEC_LOCALLY_KW' => "execLocally", - 'FORCE_FLAG_KW' => "forceFlag", - 'CLI_IN_SVR_FIREWALL_KW' => "cliInSvrFirewall", - 'REG_CHKSUM_KW' => "regChksum", - 'VERIFY_CHKSUM_KW' => "verifyChksum", - 'VERIFY_BY_SIZE_KW' => "verifyBySize", - 'OBJ_PATH_KW' => "objPath", - 'RESC_NAME_KW' => "rescName", - 'DEST_RESC_NAME_KW' => "destRescName", - 'BACKUP_RESC_NAME_KW' => "backupRescName", - 'DATA_TYPE_KW' => "dataType", - 'DATA_SIZE_KW' => "dataSize", - 'CHKSUM_KW' => "chksum", - 'VERSION_KW' => "version", - 'FILE_PATH_KW' => "filePath", - 'REPL_NUM_KW' => "replNum", - 'REPL_STATUS_KW' => "replStatus", - 'ALL_REPL_STATUS_KW' => "allReplStatus", - 'DATA_INCLUDED_KW' => "dataIncluded", - 'DATA_OWNER_KW' => "dataOwner", - 'DATA_OWNER_ZONE_KW' => "dataOwnerZone", - 'DATA_EXPIRY_KW' => "dataExpiry", - 'DATA_COMMENTS_KW' => "dataComments", - 'DATA_CREATE_KW' => "dataCreate", - 'DATA_MODIFY_KW' => "dataModify", - 'DATA_ACCESS_KW' => "dataAccess", - 'DATA_ACCESS_INX_KW' => "dataAccessInx", - 'NO_OPEN_FLAG_KW' => "noOpenFlag", - 'STREAMING_KW' => "streaming", - 'DATA_ID_KW' => "dataId", - 'COLL_ID_KW' => "collId", - 'RESC_GROUP_NAME_KW' => "rescGroupName", - 'STATUS_STRING_KW' => "statusString", - 'DATA_MAP_ID_KW' => "dataMapId", - 'NO_PARA_OP_KW' => "noParaOpr", - 'LOCAL_PATH_KW' => "localPath", - 'RSYNC_MODE_KW' => "rsyncMode", - 'RSYNC_DEST_PATH_KW' => "rsyncDestPath", - 'RSYNC_CHKSUM_KW' => "rsyncChksum", - 'CHKSUM_ALL_KW' => "ChksumAll", - 'FORCE_CHKSUM_KW' => "forceChksum", - 'COLLECTION_KW' => "collection", - 'IRODS_ADMIN_KW' => "irodsAdmin", - 'RESC_ZONE_KW' => "zoneName", - 'RESC_LOC_KW' => "rescLoc", - 'RESC_TYPE_KW' => "rescType", - 'RESC_CLASS_KW' => "rescClass", - 'RESC_VAULT_PATH_KW' => "rescVaultPath", - 'NUM_OPEN_PORTS_KW' => "numOpenPorts", - 'PARA_OPR_KW' => "paraOpr", - 'GATEWAY_ADDR_KW' => "gateWayAddr", - 'RESC_MAX_OBJ_SIZE_KW' => "rescMaxObjSize", - 'FREE_SPACE_KW' => "freeSpace", - 'FREE_SPACE_TIME_KW' => "freeSpaceTime", - 'FREE_SPACE_TIMESTAMP_KW' => "freeSpaceTimeStamp", - 'RESC_TYPE_INX_KW' => "rescTypeInx", - 'RESC_CLASS_INX_KW' => "rescClassInx", - 'RESC_ID_KW' => "rescId", - 'RESC_INFO_KW' => "rescInfo", - 'RESC_COMMENTS_KW' => "rescComments", - 'RESC_CREATE_KW' => "rescCreate", - 'RESC_MODIFY_KW' => "rescModify", - 'USER_NAME_CLIENT_KW' => "userNameClient", - 'RODS_ZONE_CLIENT_KW' => "rodsZoneClient", - 'HOST_CLIENT_KW' => "hostClient", - 'USER_TYPE_CLIENT_KW' => "userTypeClient", - 'AUTH_STR_CLIENT_KW' => "authStrClient", - 'USER_AUTH_SCHEME_CLIENT_KW' => "userAuthSchemeClient", - 'USER_INFO_CLIENT_KW' => "userInfoClient", - 'USER_COMMENT_CLIENT_KW' => "userCommentClient", - 'USER_CREATE_CLIENT_KW' => "userCreateClient", - 'USER_MODIFY_CLIENT_KW' => "userModifyClient", - 'USER_NAME_PROXY_KW' => "userNameProxy", - 'RODS_ZONE_PROXY_KW' => "rodsZoneProxy", - 'HOST_PROXY_KW' => "hostProxy", - 'USER_TYPE_PROXY_KW' => "userTypeProxy", - 'AUTH_STR_PROXY_KW' => "authStrProxy", - 'USER_AUTH_SCHEME_PROXY_KW' => "userAuthSchemeProxy", - 'USER_INFO_PROXY_KW' => "userInfoProxy", - 'USER_COMMENT_PROXY_KW' => "userCommentProxy", - 'USER_CREATE_PROXY_KW' => "userCreateProxy", - 'USER_MODIFY_PROXY_KW' => "userModifyProxy", - 'ACCESS_PERMISSION_KW' => "accessPermission", - 'COLL_NAME_KW' => "collName", - 'COLL_PARENT_NAME_KW' => "collParentName", - 'COLL_OWNER_NAME_KW' => "collOwnername", - 'COLL_OWNER_ZONE_KW' => "collOwnerZone", - 'COLL_MAP_ID_KW' => "collMapId", - 'COLL_INHERITANCE_KW' => "collInheritance", - 'COLL_COMMENTS_KW' => "collComments", - 'COLL_EXPIRY_KW' => "collExpiry", - 'COLL_CREATE_KW' => "collCreate", - 'COLL_MODIFY_KW' => "collModify", - 'COLL_ACCESS_KW' => "collAccess", - 'COLL_ACCESS_INX_KW' => "collAccessInx", - 'COLL_ID_KW' => "collId", - 'RULE_NAME_KW' => "ruleName", - 'RULE_REI_FILE_PATH_KW' => "reiFilePath", - 'RULE_USER_NAME_KW' => "userName", - 'RULE_EXE_ADDRESS_KW' => "exeAddress", - 'RULE_EXE_TIME_KW' => "exeTime", - 'RULE_EXE_FREQUENCY_KW' => "exeFrequency", - 'RULE_PRIORITY_KW' => "priority", - 'RULE_ESTIMATE_EXE_TIME_KW' => "estimateExeTime", - 'RULE_NOTIFICATION_ADDR_KW' => "notificationAddr", - 'RULE_LAST_EXE_TIME_KW' => "lastExeTime", - 'RULE_EXE_STATUS_KW' => "exeStatus", -); -$GLOBALS['PRODS_GENQUE_KEYWD_REV'] = array( - "all" => 'ALL_KW', - "copies" => 'COPIES_KW', - "execLocally" => 'EXEC_LOCALLY_KW', - "forceFlag" => 'FORCE_FLAG_KW', - "cliInSvrFirewall" => 'CLI_IN_SVR_FIREWALL_KW', - "regChksum" => 'REG_CHKSUM_KW', - "verifyChksum" => 'VERIFY_CHKSUM_KW', - "verifyBySize" => 'VERIFY_BY_SIZE_KW', - "objPath" => 'OBJ_PATH_KW', - "rescName" => 'RESC_NAME_KW', - "destRescName" => 'DEST_RESC_NAME_KW', - "backupRescName" => 'BACKUP_RESC_NAME_KW', - "dataType" => 'DATA_TYPE_KW', - "dataSize" => 'DATA_SIZE_KW', - "chksum" => 'CHKSUM_KW', - "version" => 'VERSION_KW', - "filePath" => 'FILE_PATH_KW', - "replNum" => 'REPL_NUM_KW', - "replStatus" => 'REPL_STATUS_KW', - "allReplStatus" => 'ALL_REPL_STATUS_KW', - "dataIncluded" => 'DATA_INCLUDED_KW', - "dataOwner" => 'DATA_OWNER_KW', - "dataOwnerZone" => 'DATA_OWNER_ZONE_KW', - "dataExpiry" => 'DATA_EXPIRY_KW', - "dataComments" => 'DATA_COMMENTS_KW', - "dataCreate" => 'DATA_CREATE_KW', - "dataModify" => 'DATA_MODIFY_KW', - "dataAccess" => 'DATA_ACCESS_KW', - "dataAccessInx" => 'DATA_ACCESS_INX_KW', - "noOpenFlag" => 'NO_OPEN_FLAG_KW', - "streaming" => 'STREAMING_KW', - "dataId" => 'DATA_ID_KW', - "collId" => 'COLL_ID_KW', - "rescGroupName" => 'RESC_GROUP_NAME_KW', - "statusString" => 'STATUS_STRING_KW', - "dataMapId" => 'DATA_MAP_ID_KW', - "noParaOpr" => 'NO_PARA_OP_KW', - "localPath" => 'LOCAL_PATH_KW', - "rsyncMode" => 'RSYNC_MODE_KW', - "rsyncDestPath" => 'RSYNC_DEST_PATH_KW', - "rsyncChksum" => 'RSYNC_CHKSUM_KW', - "ChksumAll" => 'CHKSUM_ALL_KW', - "forceChksum" => 'FORCE_CHKSUM_KW', - "collection" => 'COLLECTION_KW', - "irodsAdmin" => 'IRODS_ADMIN_KW', - "zoneName" => 'RESC_ZONE_KW', - "rescLoc" => 'RESC_LOC_KW', - "rescType" => 'RESC_TYPE_KW', - "rescClass" => 'RESC_CLASS_KW', - "rescVaultPath" => 'RESC_VAULT_PATH_KW', - "numOpenPorts" => 'NUM_OPEN_PORTS_KW', - "paraOpr" => 'PARA_OPR_KW', - "gateWayAddr" => 'GATEWAY_ADDR_KW', - "rescMaxObjSize" => 'RESC_MAX_OBJ_SIZE_KW', - "freeSpace" => 'FREE_SPACE_KW', - "freeSpaceTime" => 'FREE_SPACE_TIME_KW', - "freeSpaceTimeStamp" => 'FREE_SPACE_TIMESTAMP_KW', - "rescTypeInx" => 'RESC_TYPE_INX_KW', - "rescClassInx" => 'RESC_CLASS_INX_KW', - "rescId" => 'RESC_ID_KW', - "rescInfo" => 'RESC_INFO_KW', - "rescComments" => 'RESC_COMMENTS_KW', - "rescCreate" => 'RESC_CREATE_KW', - "rescModify" => 'RESC_MODIFY_KW', - "userNameClient" => 'USER_NAME_CLIENT_KW', - "rodsZoneClient" => 'RODS_ZONE_CLIENT_KW', - "hostClient" => 'HOST_CLIENT_KW', - "userTypeClient" => 'USER_TYPE_CLIENT_KW', - "authStrClient" => 'AUTH_STR_CLIENT_KW', - "userAuthSchemeClient" => 'USER_AUTH_SCHEME_CLIENT_KW', - "userInfoClient" => 'USER_INFO_CLIENT_KW', - "userCommentClient" => 'USER_COMMENT_CLIENT_KW', - "userCreateClient" => 'USER_CREATE_CLIENT_KW', - "userModifyClient" => 'USER_MODIFY_CLIENT_KW', - "userNameProxy" => 'USER_NAME_PROXY_KW', - "rodsZoneProxy" => 'RODS_ZONE_PROXY_KW', - "hostProxy" => 'HOST_PROXY_KW', - "userTypeProxy" => 'USER_TYPE_PROXY_KW', - "authStrProxy" => 'AUTH_STR_PROXY_KW', - "userAuthSchemeProxy" => 'USER_AUTH_SCHEME_PROXY_KW', - "userInfoProxy" => 'USER_INFO_PROXY_KW', - "userCommentProxy" => 'USER_COMMENT_PROXY_KW', - "userCreateProxy" => 'USER_CREATE_PROXY_KW', - "userModifyProxy" => 'USER_MODIFY_PROXY_KW', - "accessPermission" => 'ACCESS_PERMISSION_KW', - "collName" => 'COLL_NAME_KW', - "collParentName" => 'COLL_PARENT_NAME_KW', - "collOwnername" => 'COLL_OWNER_NAME_KW', - "collOwnerZone" => 'COLL_OWNER_ZONE_KW', - "collMapId" => 'COLL_MAP_ID_KW', - "collInheritance" => 'COLL_INHERITANCE_KW', - "collComments" => 'COLL_COMMENTS_KW', - "collExpiry" => 'COLL_EXPIRY_KW', - "collCreate" => 'COLL_CREATE_KW', - "collModify" => 'COLL_MODIFY_KW', - "collAccess" => 'COLL_ACCESS_KW', - "collAccessInx" => 'COLL_ACCESS_INX_KW', - "collId" => 'COLL_ID_KW', - "ruleName" => 'RULE_NAME_KW', - "reiFilePath" => 'RULE_REI_FILE_PATH_KW', - "userName" => 'RULE_USER_NAME_KW', - "exeAddress" => 'RULE_EXE_ADDRESS_KW', - "exeTime" => 'RULE_EXE_TIME_KW', - "exeFrequency" => 'RULE_EXE_FREQUENCY_KW', - "priority" => 'RULE_PRIORITY_KW', - "estimateExeTime" => 'RULE_ESTIMATE_EXE_TIME_KW', - "notificationAddr" => 'RULE_NOTIFICATION_ADDR_KW', - "lastExeTime" => 'RULE_LAST_EXE_TIME_KW', - "exeStatus" => 'RULE_EXE_STATUS_KW', -); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/RodsGenQueryNum.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/RodsGenQueryNum.inc.php deleted file mode 100644 index a65823ec87..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/RodsGenQueryNum.inc.php +++ /dev/null @@ -1,234 +0,0 @@ - '50', - 'MAX_SQL_ROWS' => '500', - 'ORDER_BY' => '1024', - 'ORDER_BY_DESC' => '2048', - 'RETURN_TOTAL_ROW_COUNT' => '32', - 'SELECT_MIN' => '2', - 'SELECT_MAX' => '3', - 'SELECT_SUM' => '4', - 'SELECT_AVG' => '5', - 'SELECT_COUNT' => '6', - 'COL_ZONE_ID' => '101', - 'COL_ZONE_NAME' => '102', - 'COL_USER_ID' => '201', - 'COL_USER_NAME' => '202', - 'COL_USER_TYPE' => '203', - 'COL_USER_ZONE' => '204', - 'COL_USER_DN' => '205', - 'COL_USER_INFO' => '206', - 'COL_USER_COMMENT' => '207', - 'COL_USER_CREATE_TIME' => '208', - 'COL_USER_MODIFY_TIME' => '209', - 'COL_R_RESC_ID' => '301', - 'COL_R_RESC_NAME' => '302', - 'COL_R_ZONE_NAME' => '303', - 'COL_R_TYPE_NAME' => '304', - 'COL_R_CLASS_NAME' => '305', - 'COL_R_LOC' => '306', - 'COL_R_VAULT_PATH' => '307', - 'COL_R_FREE_SPACE' => '308', - 'COL_R_RESC_INFO' => '309', - 'COL_R_RESC_COMMENT' => '310', - 'COL_R_CREATE_TIME' => '311', - 'COL_R_MODIFY_TIME' => '312', - 'COL_D_DATA_ID' => '401', - 'COL_D_COLL_ID' => '402', - 'COL_DATA_NAME' => '403', - 'COL_DATA_REPL_NUM' => '404', - 'COL_DATA_VERSION' => '405', - 'COL_DATA_TYPE_NAME' => '406', - 'COL_DATA_SIZE' => '407', - 'COL_D_RESC_GROUP_NAME' => '408', - 'COL_D_RESC_NAME' => '409', - 'COL_D_DATA_PATH' => '410', - 'COL_D_OWNER_NAME' => '411', - 'COL_D_OWNER_ZONE' => '412', - 'COL_D_REPL_STATUS' => '413', - 'COL_D_DATA_STATUS' => '414', - 'COL_D_DATA_CHECKSUM' => '415', - 'COL_D_EXPIRY' => '416', - 'COL_D_MAP_ID' => '417', - 'COL_D_COMMENTS' => '418', - 'COL_D_CREATE_TIME' => '419', - 'COL_D_MODIFY_TIME' => '420', - 'COL_COLL_ID' => '500', - 'COL_COLL_NAME' => '501', - 'COL_COLL_PARENT_NAME' => '502', - 'COL_COLL_OWNER_NAME' => '503', - 'COL_COLL_OWNER_ZONE' => '504', - 'COL_COLL_MAP_ID' => '505', - 'COL_COLL_INHERITANCE' => '506', - 'COL_COLL_COMMENTS' => '507', - 'COL_COLL_CREATE_TIME' => '508', - 'COL_COLL_MODIFY_TIME' => '509', - 'COL_COLL_TYPE' => '510', - 'COL_COLL_INFO1' => '511', - 'COL_COLL_INFO2' => '512', - 'COL_META_DATA_ATTR_NAME' => '600', - 'COL_META_DATA_ATTR_VALUE' => '601', - 'COL_META_DATA_ATTR_UNITS' => '602', - 'COL_META_DATA_ATTR_ID' => '603', - 'COL_META_COLL_ATTR_NAME' => '610', - 'COL_META_COLL_ATTR_VALUE' => '611', - 'COL_META_COLL_ATTR_UNITS' => '612', - 'COL_META_COLL_ATTR_ID' => '613', - 'COL_META_NAMESPACE_COLL' => '620', - 'COL_META_NAMESPACE_DATA' => '621', - 'COL_META_NAMESPACE_RESC' => '622', - 'COL_META_NAMESPACE_USER' => '623', - 'COL_META_RESC_ATTR_NAME' => '630', - 'COL_META_RESC_ATTR_VALUE' => '631', - 'COL_META_RESC_ATTR_UNITS' => '632', - 'COL_META_RESC_ATTR_ID' => '633', - 'COL_META_USER_ATTR_NAME' => '640', - 'COL_META_USER_ATTR_VALUE' => '641', - 'COL_META_USER_ATTR_UNITS' => '642', - 'COL_META_USER_ATTR_ID' => '643', - 'COL_DATA_ACCESS_TYPE' => '700', - 'COL_DATA_ACCESS_NAME' => '701', - 'COL_DATA_TOKEN_NAMESPACE' => '702', - 'COL_DATA_ACCESS_USER_ID' => '703', - 'COL_DATA_ACCESS_DATA_ID' => '704', - 'COL_RESC_GROUP_RESC_ID' => '800', - 'COL_RESC_GROUP_NAME' => '801', - 'COL_USER_GROUP_ID' => '900', - 'COL_USER_GROUP_NAME' => '901', - 'COL_RULE_EXEC_ID' => '1000', - 'COL_RULE_EXEC_NAME' => '1001', - 'COL_RULE_EXEC_REI_FILE_PATH' => '1002', - 'COL_RULE_EXEC_USER_NAME' => '1003', - 'COL_RULE_EXEC_ADDRESS' => '1004', - 'COL_RULE_EXEC_TIME' => '1005', - 'COL_RULE_EXEC_FREQUENCY' => '1006', - 'COL_RULE_EXEC_PRIORITY' => '1007', - 'COL_RULE_EXEC_ESTIMATED_EXE_TIME' => '1008', - 'COL_RULE_EXEC_NOTIFICATION_ADDR' => '1009', - 'COL_RULE_EXEC_LAST_EXE_TIME' => '1010', - 'COL_RULE_EXEC_STATUS' => '1011', - 'COL_TOKEN_NAMESPACE' => '1100', - 'COL_TOKEN_ID' => '1101', - 'COL_TOKEN_NAME' => '1102', - 'COL_TOKEN_VALUE' => '1103', - 'COL_TOKEN_VALUE2' => '1104', - 'COL_TOKEN_VALUE3' => '1105', - 'COL_TOKEN_COMMENT' => '1106', -); -$GLOBALS['PRODS_GENQUE_NUMS_REV'] = array( - '50' => 'MAX_SQL_ATTR', - '500' => 'MAX_SQL_ROWS', - '1024' => 'ORDER_BY', - '2048' => 'ORDER_BY_DESC', - '32' => 'RETURN_TOTAL_ROW_COUNT', - '2' => 'SELECT_MIN', - '3' => 'SELECT_MAX', - '4' => 'SELECT_SUM', - '5' => 'SELECT_AVG', - '6' => 'SELECT_COUNT', - '101' => 'COL_ZONE_ID', - '102' => 'COL_ZONE_NAME', - '201' => 'COL_USER_ID', - '202' => 'COL_USER_NAME', - '203' => 'COL_USER_TYPE', - '204' => 'COL_USER_ZONE', - '205' => 'COL_USER_DN', - '206' => 'COL_USER_INFO', - '207' => 'COL_USER_COMMENT', - '208' => 'COL_USER_CREATE_TIME', - '209' => 'COL_USER_MODIFY_TIME', - '301' => 'COL_R_RESC_ID', - '302' => 'COL_R_RESC_NAME', - '303' => 'COL_R_ZONE_NAME', - '304' => 'COL_R_TYPE_NAME', - '305' => 'COL_R_CLASS_NAME', - '306' => 'COL_R_LOC', - '307' => 'COL_R_VAULT_PATH', - '308' => 'COL_R_FREE_SPACE', - '309' => 'COL_R_RESC_INFO', - '310' => 'COL_R_RESC_COMMENT', - '311' => 'COL_R_CREATE_TIME', - '312' => 'COL_R_MODIFY_TIME', - '401' => 'COL_D_DATA_ID', - '402' => 'COL_D_COLL_ID', - '403' => 'COL_DATA_NAME', - '404' => 'COL_DATA_REPL_NUM', - '405' => 'COL_DATA_VERSION', - '406' => 'COL_DATA_TYPE_NAME', - '407' => 'COL_DATA_SIZE', - '408' => 'COL_D_RESC_GROUP_NAME', - '409' => 'COL_D_RESC_NAME', - '410' => 'COL_D_DATA_PATH', - '411' => 'COL_D_OWNER_NAME', - '412' => 'COL_D_OWNER_ZONE', - '413' => 'COL_D_REPL_STATUS', - '414' => 'COL_D_DATA_STATUS', - '415' => 'COL_D_DATA_CHECKSUM', - '416' => 'COL_D_EXPIRY', - '417' => 'COL_D_MAP_ID', - '418' => 'COL_D_COMMENTS', - '419' => 'COL_D_CREATE_TIME', - '420' => 'COL_D_MODIFY_TIME', - '500' => 'COL_COLL_ID', - '501' => 'COL_COLL_NAME', - '502' => 'COL_COLL_PARENT_NAME', - '503' => 'COL_COLL_OWNER_NAME', - '504' => 'COL_COLL_OWNER_ZONE', - '505' => 'COL_COLL_MAP_ID', - '506' => 'COL_COLL_INHERITANCE', - '507' => 'COL_COLL_COMMENTS', - '508' => 'COL_COLL_CREATE_TIME', - '509' => 'COL_COLL_MODIFY_TIME', - '510' => 'COL_COLL_TYPE', - '511' => 'COL_COLL_INFO1', - '512' => 'COL_COLL_INFO2', - '600' => 'COL_META_DATA_ATTR_NAME', - '601' => 'COL_META_DATA_ATTR_VALUE', - '602' => 'COL_META_DATA_ATTR_UNITS', - '603' => 'COL_META_DATA_ATTR_ID', - '610' => 'COL_META_COLL_ATTR_NAME', - '611' => 'COL_META_COLL_ATTR_VALUE', - '612' => 'COL_META_COLL_ATTR_UNITS', - '613' => 'COL_META_COLL_ATTR_ID', - '620' => 'COL_META_NAMESPACE_COLL', - '621' => 'COL_META_NAMESPACE_DATA', - '622' => 'COL_META_NAMESPACE_RESC', - '623' => 'COL_META_NAMESPACE_USER', - '630' => 'COL_META_RESC_ATTR_NAME', - '631' => 'COL_META_RESC_ATTR_VALUE', - '632' => 'COL_META_RESC_ATTR_UNITS', - '633' => 'COL_META_RESC_ATTR_ID', - '640' => 'COL_META_USER_ATTR_NAME', - '641' => 'COL_META_USER_ATTR_VALUE', - '642' => 'COL_META_USER_ATTR_UNITS', - '643' => 'COL_META_USER_ATTR_ID', - '700' => 'COL_DATA_ACCESS_TYPE', - '701' => 'COL_DATA_ACCESS_NAME', - '702' => 'COL_DATA_TOKEN_NAMESPACE', - '703' => 'COL_DATA_ACCESS_USER_ID', - '704' => 'COL_DATA_ACCESS_DATA_ID', - '800' => 'COL_RESC_GROUP_RESC_ID', - '801' => 'COL_RESC_GROUP_NAME', - '900' => 'COL_USER_GROUP_ID', - '901' => 'COL_USER_GROUP_NAME', - '1000' => 'COL_RULE_EXEC_ID', - '1001' => 'COL_RULE_EXEC_NAME', - '1002' => 'COL_RULE_EXEC_REI_FILE_PATH', - '1003' => 'COL_RULE_EXEC_USER_NAME', - '1004' => 'COL_RULE_EXEC_ADDRESS', - '1005' => 'COL_RULE_EXEC_TIME', - '1006' => 'COL_RULE_EXEC_FREQUENCY', - '1007' => 'COL_RULE_EXEC_PRIORITY', - '1008' => 'COL_RULE_EXEC_ESTIMATED_EXE_TIME', - '1009' => 'COL_RULE_EXEC_NOTIFICATION_ADDR', - '1010' => 'COL_RULE_EXEC_LAST_EXE_TIME', - '1011' => 'COL_RULE_EXEC_STATUS', - '1100' => 'COL_TOKEN_NAMESPACE', - '1101' => 'COL_TOKEN_ID', - '1102' => 'COL_TOKEN_NAME', - '1103' => 'COL_TOKEN_VALUE', - '1104' => 'COL_TOKEN_VALUE2', - '1105' => 'COL_TOKEN_VALUE3', - '1106' => 'COL_TOKEN_COMMENT', -); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/autoload.inc.php b/apps/files_external/3rdparty/irodsphp/prods/src/autoload.inc.php deleted file mode 100644 index 593b901959..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/autoload.inc.php +++ /dev/null @@ -1,47 +0,0 @@ -read())) { - if ($folder != "." && $folder != "..") { - if (is_dir(CLASS_DIR . $sub . $folder)) { - $subFolder = classFolder($className, $sub . $folder . "/"); - - if ($subFolder) - return $subFolder; - } - } - } - $dir->close(); - return false; -} - -spl_autoload_register('__autoload'); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RODSPacket.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RODSPacket.class.php deleted file mode 100644 index e5cff1f60e..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RODSPacket.class.php +++ /dev/null @@ -1,248 +0,0 @@ - array ("type" => NULL, "msgLen" => 0, - "errorLen" => 0, "bsLen" => 0, "intInfo" => 0), - "StartupPack_PI" => array ("irodsProt" => 1, "connectCnt" => 0, - "proxyUser" => NULL, "proxyRcatZone" => NULL, "clientUser" => NULL, - "clientRcatZone" => NULL, "relVersion" => NULL, - "apiVersion" => NULL, "option" => NULL ), - "Version_PI" => array ("status"=>0,"relVersion"=>NULL,"apiVersion"=>NULL), - "authResponseInp_PI" => array("response" => NULL, "username" => NULL), - "authRequestOut_PI" => array("challenge" => NULL) -); -*/ - -class RODSPacket -{ - protected $type; // type of packet - protected $packlets; // (array of mixed) main message body - - public function __construct($type = NULL, array $arr = NULL) - { - if (!isset($type)) - return; - - $this->type = $type; - $this->packlets = $arr; - } - - public function toXML() - { - if (empty($this->type)) - return NULL; - - $doc = new DOMDocument(); - $root = $this->toDOMElement($doc); - $doc->appendChild($root); - return ($doc->saveXML($root, LIBXML_NOEMPTYTAG)); - } - - /* - public function fromXML($str) - { - try { - $xml = new SimpleXMLElement($str); - } catch (Exception $e) { - throw new RODSException("RODSPacket::fromXML failed. ". - "Mal-formated XML: '$str'\n", - PERR_INTERNAL_ERR); - } - - if (isset($this->type)&&($this->type!=$xml->getName())) - { - throw new RODSException("RODSPacket::fromXML failed. ". - "Possible type mismatch! expected type:".$this->type." but got: ". - $xml->getName()." \n", - PERR_INTERNAL_ERR); - } - - $this->type=$xml->getName(); - - foreach($xml as $key => $val) - { - if (!array_key_exists($key,$this->msg)) - { - throw new RODSException("RODSPacket::fromXML failed. ". - "Possible type mismatch! expected key '$key' doesn't exists\n", - PERR_INTERNAL_ERR); - } - $this->msg[$key]=(string)$val; - } - } - */ - - public static function parseXML($xmlstr) - { - if (false == ($doc = DOMDocument::loadXML($xmlstr))) { - throw new RODSException("RODSPacket::parseXML failed. " . - "Failed to loadXML(). The xmlstr is: $xmlstr\n", - PERR_UNEXPECTED_PACKET_FORMAT); - } - - $rp_classname = "RP_" . substr($doc->tagName, 0, strlen($doc->tagName) - 3); - $packet = new $rp_classname(); - $packet->fromDOM($doc); - } - - /* - public function fromDOM(DOMNode $domnode) - { - if (!isset($this->packlets)) - return; - - $i=0; - $domnode_children=$domnode->childNodes; - - foreach($this->packlets as $packlet_key => &$packlet_val) - { - $domnode_child=$domnode_children->item($i++); - - // check if the tag names are expected - if ($domnode_child->tagName!=$packlet_key) - { - throw new RODSException("RODSPacket::fromDOM failed. ". - "Expecting packlet:$packlet_key, but got:".$domnode_child->tagName." \n", - PERR_UNEXPECTED_PACKET_FORMAT); - } - - if (is_a($packlet_val, "RODSPacket")) //if expecting sub packet - { - $packlet_val->fromDOM($domnode_child); - } - else //if expecting an string - { - - } - } - } - - */ - - public function fromSXE(SimpleXMLElement $sxe) - { - if (!isset($this->packlets)) - return; - - foreach ($this->packlets as $packlet_key => &$packlet_val) { - if ($packlet_val instanceof RODSPacket) //if expecting sub packet - { - if (!isset($sxe->$packlet_key)) { - throw new RODSException("RODSPacket(" . get_class($this) . ")::fromSXE failed. " . - "Failed to find expected packlet: '$packlet_key' \n", - "PERR_UNEXPECTED_PACKET_FORMAT"); - } - $packlet_val->fromSXE($sxe->$packlet_key); - } else - if (is_array($packlet_val)) //if expecting array - { - if (isset($sxe->$packlet_key)) { - $packlet_val = array(); - foreach ($sxe->$packlet_key as $sxe_val) { - if ((!empty($this->array_rp_type)) && - (!empty($this->array_rp_type["$packlet_key"])) - ) // if it's an array of packets - { - $class_name = $this->array_rp_type[$packlet_key]; - $sub_array_packet = new $class_name(); - $sub_array_packet->fromSXE($sxe_val); - $packlet_val[] = $sub_array_packet; - } else { - $packlet_val[] = (string)$sxe_val; - } - } - } - - } else { - if (isset($sxe->$packlet_key)) { - $packlet_val = (string)$sxe->$packlet_key; - } - } - } - /* - foreach($sxe->children() as $child) - { - $tagname=$child->getName(); - if(substr($tagname,-3,3)=="_PI") - { - $rp_classname="RP_".substr($name,0,strlen($name)-3); - $child_rp=new $rp_classname(); - $child_rp->fromSXE($child); - } - else - { - $this->packlets[$child->getName()]=(string)$child; - } - } - */ - } - - public function toDOMElement(DOMDocument $doc) - { - if (empty($this->type)) - return NULL; - - $node = $doc->createElement($this->type); - - foreach ($this->packlets as $name => $packlet) { - if ($packlet instanceof RODSPacket) //if node is a packet - { - $child_node = $packlet->toDOMElement($doc); - if (isset($child_node)) - $node->appendChild($packlet->toDOMElement($doc)); - } else - if (is_array($packlet)) //if node is an array - { - if (isset($packlet)) { - foreach ($packlet as $sub_packlet) { - if ($sub_packlet instanceof RODSPacket) //if sub_node is a packet - { - $child_node = $sub_packlet->toDOMElement($doc); - if (isset($child_node)) - $node->appendChild($sub_packlet->toDOMElement($doc)); - } else { - //echo "sub_packlet = $sub_packlet
\n"; - $node->appendChild($doc->createElement($name, htmlspecialchars($sub_packlet))); - } - } - } - } else //if node holds a string - { //echo "packlet = $packlet
\n"; - $node->appendChild($doc->createElement($name, htmlspecialchars($packlet))); - } - } - - return $node; - } - - public function __get($name) - { - if (array_key_exists($name, $this->packlets)) - return $this->packlets[$name]; - else { - debug_print_backtrace(); - throw new RODSException("RODSPacket::__get() failed. Trying to access field '$name' that doesn't exist!", - "PERR_INTERNAL_ERR"); - } - } - - public function __set($name, $val) - { - if (array_key_exists($name, $this->packlets)) - $this->packlets[$name] = $val; - else - throw new RODSException("RODSPacket::__set() failed. Trying to access field '$name' that doesn't exist!", - "PERR_INTERNAL_ERR"); - } - - /* - public static function makeStartupPack($user,$zone) - { - $msg=array(1,0,$user,$zone,$user,$zone,'rods0.5','a',NULL); - return (new RODSPacket("StartupPack_PI",$msg)); - } - */ -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_BinBytesBuf.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_BinBytesBuf.class.php deleted file mode 100644 index a7598bb7e6..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_BinBytesBuf.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $buflen, "buf" => $buf); - parent::__construct("BinBytesBuf_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_CollInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_CollInp.class.php deleted file mode 100644 index 05c51cf56c..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_CollInp.class.php +++ /dev/null @@ -1,17 +0,0 @@ - $collName, - 'KeyValPair_PI' => $KeyValPair_PI); - parent::__construct("CollInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_CollOprStat.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_CollOprStat.class.php deleted file mode 100644 index a9140050bc..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_CollOprStat.class.php +++ /dev/null @@ -1,15 +0,0 @@ - $filesCnt, "totalFileCnt" => $totalFileCnt, - 'bytesWritten' => $bytesWritten, 'lastObjPath' => $lastObjPath); - parent::__construct("CollOprStat_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_DataObjCopyInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_DataObjCopyInp.class.php deleted file mode 100644 index 481ff34a22..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_DataObjCopyInp.class.php +++ /dev/null @@ -1,17 +0,0 @@ - $src, 'dest' => $dest); - parent::__construct("DataObjCopyInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_DataObjInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_DataObjInp.class.php deleted file mode 100644 index f6200d1761..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_DataObjInp.class.php +++ /dev/null @@ -1,20 +0,0 @@ - $objPath, 'createMode' => $createMode, - 'openFlags' => $openFlags, 'offset' => $offset, "dataSize" => $dataSize, - "numThreads" => $numThreads, "oprType" => $oprType, - 'KeyValPair_PI' => $KeyValPair_PI); - parent::__construct("DataObjInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ExecCmdOut.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ExecCmdOut.class.php deleted file mode 100644 index a7559e3c25..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ExecCmdOut.class.php +++ /dev/null @@ -1,54 +0,0 @@ - $buf); - parent::__construct("ExecCmdOut_PI", $packlets); - } - - public function fromSXE(SimpleXMLElement $sxe) - { - $binbytes = "BinBytesBuf_PI"; - $name = "buf"; - - if (!isset($this->packlets)) - return; - - $packlet_value = ""; - try { - foreach ($sxe->$binbytes as $binpacket) { - if (strlen($binpacket->$name) > 0) { - $decoded_value = base64_decode($binpacket->$name); - $packlet_value .= $decoded_value; - } - } - - // can't find a better way yet to get rid of the garbage on the end of the string ... - $len = strlen($packlet_value); - $cleaned_value = ""; - for ($i = 0; $i < $len; $i++) { - if (ord($packlet_value{$i}) <= 0) break; - $cleaned_value .= $packlet_value{$i}; - } - - $this->packlets[$name] = $cleaned_value; - $this->packlets["buflen"] = $i; - } catch (Exception $ex) { - $this->packlets[$name] = ""; - } - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ExecMyRuleInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ExecMyRuleInp.class.php deleted file mode 100644 index 2eb5dbd6ff..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ExecMyRuleInp.class.php +++ /dev/null @@ -1,20 +0,0 @@ - $myRule, "RHostAddr_PI" => $RHostAddr_PI, - "KeyValPair_PI" => $KeyValPair_PI, "outParamDesc" => $outParamDesc, - "MsParamArray_PI" => $MsParamArray_PI); - parent::__construct("ExecMyRuleInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_GenQueryInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_GenQueryInp.class.php deleted file mode 100644 index cf4bf34060..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_GenQueryInp.class.php +++ /dev/null @@ -1,23 +0,0 @@ - $maxRows, 'continueInx' => $continueInx, - 'partialStartIndex' => $partialStartIndex, 'options' => $options, - 'KeyValPair_PI' => $KeyValPair_PI, 'InxIvalPair_PI' => $InxIvalPair_PI, - 'InxValPair_PI' => $InxValPair_PI); - parent::__construct("GenQueryInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_GenQueryOut.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_GenQueryOut.class.php deleted file mode 100644 index afec88c45b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_GenQueryOut.class.php +++ /dev/null @@ -1,20 +0,0 @@ -array_rp_type = array("SqlResult_PI" => "RP_SqlResult"); - - $packlets = array("rowCnt" => $rowCnt, 'attriCnt' => $attriCnt, - 'continueInx' => $continueInx, 'totalRowCount' => $totalRowCount, - 'SqlResult_PI' => $SqlResult_PI); - parent::__construct("GenQueryOut_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_InxIvalPair.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_InxIvalPair.class.php deleted file mode 100644 index e8af5c9fc5..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_InxIvalPair.class.php +++ /dev/null @@ -1,25 +0,0 @@ - $iiLen, 'inx' => $inx, 'ivalue' => $ivalue); - parent::__construct("InxIvalPair_PI", $packlets); - } - - public function fromAssocArray($array) - { - if (!empty($array)) { - $this->packlets["iiLen"] = count($array); - $this->packlets["inx"] = array_keys($array); - $this->packlets["ivalue"] = array_values($array); - } else { - $this->packlets["iiLen"] = 0; - $this->packlets["inx"] = array(); - $this->packlets["ivalue"] = array(); - } - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_InxValPair.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_InxValPair.class.php deleted file mode 100644 index 4a08780f4a..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_InxValPair.class.php +++ /dev/null @@ -1,42 +0,0 @@ - $isLen, 'inx' => $inx, 'svalue' => $svalue); - parent::__construct("InxValPair_PI", $packlets); - } - - public function fromAssocArray($array) - { - if (!empty($array)) { - $this->packlets["isLen"] = count($array); - $this->packlets["inx"] = array_keys($array); - $this->packlets["svalue"] = array_values($array); - } else { - $this->packlets["isLen"] = 0; - $this->packlets["inx"] = array(); - $this->packlets["svalue"] = array(); - } - } - - public function fromRODSQueryConditionArray($array) - { - $this->packlets["isLen"] = 0; - $this->packlets["inx"] = array(); - $this->packlets["svalue"] = array(); - - if (!isset($array)) return; - - $this->packlets["isLen"] = count($array); - foreach ($array as $cond) { - $this->packlets["inx"][] = $cond->name; - $this->packlets["svalue"][] = "$cond->op '$cond->value'"; - //echo "
 $cond->op '$cond->value' 
"; - } - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_KeyValPair.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_KeyValPair.class.php deleted file mode 100644 index 905d88bc8a..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_KeyValPair.class.php +++ /dev/null @@ -1,45 +0,0 @@ - $ssLen, 'keyWord' => $keyWord, - 'svalue' => $svalue); - parent::__construct("KeyValPair_PI", $packlets); - } - - public function fromAssocArray(array $array) - { - if (!empty($array)) { - $this->packlets["ssLen"] = count($array); - $this->packlets["keyWord"] = array_keys($array); - $this->packlets["svalue"] = array_values($array); - } else { - $this->packlets["ssLen"] = 0; - $this->packlets["keyWord"] = array(); - $this->packlets["svalue"] = array(); - } - } - - public function fromRODSQueryConditionArray($array) - { - $this->packlets["ssLen"] = 0; - $this->packlets["keyWord"] = array(); - $this->packlets["svalue"] = array(); - - if (!isset($array)) return; - - $this->packlets["ssLen"] = count($array); - foreach ($array as $cond) { - $this->packlets["keyWord"][] = $cond->name; - $this->packlets["svalue"][] = "$cond->op '$cond->value'"; - } - } -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MiscSvrInfo.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MiscSvrInfo.class.php deleted file mode 100644 index 4f54c9c4e7..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MiscSvrInfo.class.php +++ /dev/null @@ -1,15 +0,0 @@ - $serverType, 'relVersion' => $relVersion, - 'apiVersion' => $apiVersion, 'rodsZone' => $rodsZone); - parent::__construct("MiscSvrInfo_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ModAVUMetadataInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ModAVUMetadataInp.class.php deleted file mode 100644 index 467541734d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ModAVUMetadataInp.class.php +++ /dev/null @@ -1,16 +0,0 @@ - $arg0, "arg1" => $arg1, "arg2" => $arg2, - "arg3" => $arg3, "arg4" => $arg4, "arg5" => $arg5, - "arg6" => $arg6, "arg7" => $arg7, "arg8" => $arg8, "arg9" => $arg9); - parent::__construct("ModAVUMetadataInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsParam.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsParam.class.php deleted file mode 100644 index fa5d4fcc3d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsParam.class.php +++ /dev/null @@ -1,43 +0,0 @@ - $label, "type" => $inOutStruct->type, - $inOutStruct->type => $inOutStruct, "BinBytesBuf_PI" => $BinBytesBuf_PI); - parent::__construct("MsParam_PI", $packlets); - } - - // need to overwrite it's parent function here, since $inOutStruct->type - // can be undefined, when it's parent packet class was defined. - public function fromSXE(SimpleXMLElement $sxe) - { - if (!isset($this->packlets)) - return; - - $this->packlets["label"] = (string)$sxe->label; - $this->packlets["type"] = (string)$sxe->type; - - $typename = $this->packlets["type"]; //type of the expected packet - if (substr($typename, -3, 3) != "_PI") { - throw new RODSException("RP_MsParam::fromSXE " . - "The XML node's type is unexpected: '$typename' " . - " expecting some thing like xxx_PI", - "SYS_PACK_INSTRUCT_FORMAT_ERR"); - } - $rp_classname = "RP_" . substr($typename, 0, strlen($typename) - 3); - $inOutStruct = new $rp_classname(); - $inOutStruct->fromSXE($sxe->$typename); - $this->packlets["$typename"] = $inOutStruct; - - $this->packlets['BinBytesBuf_PI'] = new RP_BinBytesBuf(); - $this->packlets['BinBytesBuf_PI']->fromSXE($sxe->BinBytesBuf_PI); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsParamArray.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsParamArray.class.php deleted file mode 100644 index b664abe62b..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsParamArray.class.php +++ /dev/null @@ -1,19 +0,0 @@ -array_rp_type = array("MsParam_PI" => "RP_MsParam"); - - $packlets = array("paramLen" => count($MsParam_PI), - "oprType" => $oprType, "MsParam_PI" => $MsParam_PI); - parent::__construct("MsParamArray_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsgHeader.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsgHeader.class.php deleted file mode 100644 index f1b03f779d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_MsgHeader.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $type, "msgLen" => $msgLen, - "errorLen" => $errorLen, "bsLen" => $bsLen, "intInfo" => $intInfo); - parent::__construct("MsgHeader_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_RHostAddr.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_RHostAddr.class.php deleted file mode 100644 index 2ac70dc22c..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_RHostAddr.class.php +++ /dev/null @@ -1,13 +0,0 @@ - $hostAddr, "rodsZone" => $rodsZone, - "port" => $port); - parent::__construct("RHostAddr_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_RodsObjStat.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_RodsObjStat.class.php deleted file mode 100644 index 96f427a2de..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_RodsObjStat.class.php +++ /dev/null @@ -1,18 +0,0 @@ - $objSize, 'objType' => $objType, - 'numCopies' => $numCopies, 'dataId' => $dataId, "chksum" => $chksum, - "ownerName" => $ownerName, "ownerZone" => $ownerZone, - 'createTime' => $createTime, 'modifyTime' => $modifyTime); - parent::__construct("RodsObjStat_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_STR.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_STR.class.php deleted file mode 100644 index af7739988d..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_STR.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $myStr); - parent::__construct("STR_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_SqlResult.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_SqlResult.class.php deleted file mode 100644 index e6ee1c3adb..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_SqlResult.class.php +++ /dev/null @@ -1,13 +0,0 @@ - $attriInx, 'reslen' => $reslen, 'value' => $value); - parent::__construct("SqlResult_PI", $packlets); - } - - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_StartupPack.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_StartupPack.class.php deleted file mode 100644 index 700fbd3442..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_StartupPack.class.php +++ /dev/null @@ -1,16 +0,0 @@ - 1, "connectCnt" => 0, - "proxyUser" => $user, "proxyRcatZone" => $zone, "clientUser" => $user, - "clientRcatZone" => $zone, "relVersion" => $relVersion, - "apiVersion" => $apiVersion, "option" => $option); - parent::__construct("StartupPack_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_TransStat.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_TransStat.class.php deleted file mode 100644 index 5c962649df..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_TransStat.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $numThreads, - 'bytesWritten' => $bytesWritten); - parent::__construct("TransStat_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_Version.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_Version.class.php deleted file mode 100644 index 9fa9b7d1c3..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_Version.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $status, "relVersion" => $relVersion, - "apiVersion" => $apiVersion); - parent::__construct("Version_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_authRequestOut.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_authRequestOut.class.php deleted file mode 100644 index a702650c0e..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_authRequestOut.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $challenge); - parent::__construct("authRequestOut_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_authResponseInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_authResponseInp.class.php deleted file mode 100644 index 3f9cbc618f..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_authResponseInp.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $response, "username" => $username); - parent::__construct("authResponseInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjCloseInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjCloseInp.class.php deleted file mode 100644 index d37afe23c9..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjCloseInp.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $l1descInx, - 'bytesWritten' => $bytesWritten); - parent::__construct("dataObjCloseInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjReadInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjReadInp.class.php deleted file mode 100644 index 31b1235471..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjReadInp.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $l1descInx, - 'len' => $len); - parent::__construct("dataObjReadInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjWriteInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjWriteInp.class.php deleted file mode 100644 index 175b7e8340..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_dataObjWriteInp.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $dataObjInx, - 'len' => $len); - parent::__construct("dataObjWriteInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_fileLseekInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_fileLseekInp.class.php deleted file mode 100644 index 83b77f4704..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_fileLseekInp.class.php +++ /dev/null @@ -1,14 +0,0 @@ - $fileInx, "offset" => $offset, - 'whence' => $whence); - parent::__construct("fileLseekInp_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_fileLseekOut.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_fileLseekOut.class.php deleted file mode 100644 index 45811e7ca6..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_fileLseekOut.class.php +++ /dev/null @@ -1,13 +0,0 @@ - $offset); - parent::__construct("fileLseekOut_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_getTempPasswordOut.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_getTempPasswordOut.class.php deleted file mode 100644 index 29c1001df6..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_getTempPasswordOut.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $stringToHashWith); - parent::__construct("getTempPasswordOut_PI", $packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_pamAuthRequestInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_pamAuthRequestInp.class.php deleted file mode 100644 index e42ac918d4..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_pamAuthRequestInp.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $pamUser, "pamPassword" => $pamPassword, "timeToLive" => $timeToLive); - parent::__construct("pamAuthRequestInp_PI",$packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_pamAuthRequestOut.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_pamAuthRequestOut.class.php deleted file mode 100644 index b3ec130655..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_pamAuthRequestOut.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $irodsPamPassword); - parent::__construct("pamAuthRequestOut_PI",$packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_sslEndInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_sslEndInp.class.php deleted file mode 100644 index 26470378a7..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_sslEndInp.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $arg0); - parent::__construct("sslEndInp_PI",$packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_sslStartInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_sslStartInp.class.php deleted file mode 100644 index a23756e786..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_sslStartInp.class.php +++ /dev/null @@ -1,12 +0,0 @@ - $arg0); - parent::__construct("sslStartInp_PI",$packlets); - } - -} diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ticketAdminInp.class.php b/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ticketAdminInp.class.php deleted file mode 100644 index ec849b68db..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/packet/RP_ticketAdminInp.class.php +++ /dev/null @@ -1,30 +0,0 @@ - to use it, create -> to... create!, - $arg2 = '', // the actual ticket - $arg3 = '', // "read" or "write" -> in case of "create" above - $arg4 = '', // full path to the resource, e.g.: /tempZone/home/rods/as - $arg5 = '', - $arg6 = '') - { - - $packlets = array( 'arg1' => $arg1, - 'arg2' => $arg2, - 'arg3' => $arg3, - 'arg4' => $arg4, - 'arg5' => $arg5, - 'arg6' => $arg6, - ); - parent::__construct('ticketAdminInp_PI', $packlets); - } - -} \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/prods.ini b/apps/files_external/3rdparty/irodsphp/prods/src/prods.ini deleted file mode 100644 index 5c81a71de7..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/prods.ini +++ /dev/null @@ -1,15 +0,0 @@ -; Configuration file for the Prods API - -[ssl] -; Require verification of SSL certificate used. Default "false". -;verify_peer = "true" -; Allow self-signed certificates. Requires verify_peer. Default "false". -;allow_self_signed = "true" -; Location of Certificate Authority file on local filesystem which -; should be used with verify_peer equal "true" to authenticate -; the identity of the remote peer. -;cafile = "/path/to/cert.pem" -; If cafile is not specified or if the certificate is not found there, -; the directory pointed to by capath is searched for a suitable -; certificate. capath must be a correctly hashed certificate directory. -;capath = "/path/to/certfiles" diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/release_notes.txt b/apps/files_external/3rdparty/irodsphp/prods/src/release_notes.txt deleted file mode 100644 index 7d892eedb6..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/release_notes.txt +++ /dev/null @@ -1,31 +0,0 @@ - -*'''Project''': iRODS PHP Library PRODS and PRODS Web Browser -*'''Date''': 11/26/2012 -*'''Release Version''': 3.2.0 Release -*'''git tag''': 3.2.0 - -==News== - -This is the consolidated and updated release of the PRODS PHP library for iRODS. This library provides a pure-PHP interface to the iRODS system. This library is suitable for simple and quick interfaces to the iRODS data grid, and will be maintained for stability and compatibility. If advanced or higher-performance interfaces are desired, the Jargon Java API should be considered. Note that PHP, Jython, JRuby, Groovy, and other JVM dynamic languages can be used with Jarogn. - -The PRODS PHP Web Browser is also included in this project, and remains supported. Note that the PHP Web Browser functionality has been subsumed by the idrop-web browser and idrop-swing client. - -Please go to [[https://code.renci.org/gf/project/irodsphp/] for the latest news and info. - -Note that the git repository is now the canonical version of the PHP code. The code in the iRODS SVN server is deprecated and will be taken down at the 3.0.0 release point. There may be other versions in Google Code and other places, but these should be considered obsolete. - - -==Requirements== - -==Libraries== - -==Features== - -*[#1076] irods 3.2 release activities -**Added a LICENSE.txt file at the top project level - - -==Bug Fixes== - -*[#1071] php uses self-closing tags for empty HTML tags -**Added patch suggested by community Changing line 41 in RODSPacket.class.php (in PRods) from return ($doc->saveXML($root)); to return ($doc->saveXML($root, LIBXML_NOEMPTYTAG)); \ No newline at end of file diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsAPINum.php b/apps/files_external/3rdparty/irodsphp/prods/src/setRodsAPINum.php deleted file mode 100644 index 98c1f6cabd..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsAPINum.php +++ /dev/null @@ -1,68 +0,0 @@ - 1) { - if (empty($val1)) $val1 = trim($token); - else $val2 = trim($token); - } - } - if ((!empty($val1)) && (!empty($val2))) { - array_push($value_pairs, array($val1, $val2)); - } - } -} -var_dump($value_pairs); -foreach ($new_api_nums as $new_code_pair) { - if ((!is_array($new_code_pair)) || (count($new_code_pair) != 2)) - die("unexpected new_code_pair:$new_code_pair\n"); - array_push($value_pairs, $new_code_pair); -} - -$outputstr = " '$val2',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . '$GLOBALS[\'PRODS_API_NUMS_REV\']=array(' . "\n"; -foreach ($value_pairs as $value_pair) { - $val1 = $value_pair[0]; - $val2 = $value_pair[1]; - $outputstr = $outputstr . " '$val2' => '$val1',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . "?>\n"; -file_put_contents($prods_api_num_file, $outputstr); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsErrorCodes.php b/apps/files_external/3rdparty/irodsphp/prods/src/setRodsErrorCodes.php deleted file mode 100644 index 142b4af570..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsErrorCodes.php +++ /dev/null @@ -1,73 +0,0 @@ - 3) { - if (empty($val1)) $val1 = trim($token); - else $val2 = trim($token); - } - } - if ((!empty($val1)) && (!empty($val2))) { - array_push($value_pairs, array($val1, $val2)); - } - } -} - -foreach ($new_error_codes as $new_code_pair) { - if ((!is_array($new_code_pair)) || (count($new_code_pair) != 2)) - die("unexpected new_code_pair:$new_code_pair\n"); - array_push($value_pairs, $new_code_pair); -} - -$outputstr = " '$val2',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . '$GLOBALS[\'PRODS_ERR_CODES_REV\']=array(' . "\n"; -foreach ($value_pairs as $value_pair) { - $val1 = $value_pair[0]; - $val2 = $value_pair[1]; - $outputstr = $outputstr . " '$val2' => '$val1',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . "?>\n"; -file_put_contents($prods_error_table_file, $outputstr); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsGenQueryKeyWd.php b/apps/files_external/3rdparty/irodsphp/prods/src/setRodsGenQueryKeyWd.php deleted file mode 100644 index 5a5968d25a..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsGenQueryKeyWd.php +++ /dev/null @@ -1,71 +0,0 @@ - 1) { - if (empty($val1)) $val1 = trim($token); - else { - - if (($token{0} == '"') /*&&($token{strlen($token)-1}=='"')*/) { - if (empty($val2)) - $val2 = trim($token); - } - } - } - } - if ((!empty($val1)) && (!empty($val2))) { - array_push($value_pairs, array($val1, $val2)); - } - } -} -foreach ($new_genque_keywds as $new_code_pair) { - if ((!is_array($new_code_pair)) || (count($new_code_pair) != 2)) - die("unexpected new_code_pair:$new_code_pair\n"); - array_push($value_pairs, $new_code_pair); -} - -$outputstr = " $val2,\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . '$GLOBALS[\'PRODS_GENQUE_KEYWD_REV\']=array(' . "\n"; -foreach ($value_pairs as $value_pair) { - $val1 = $value_pair[0]; - $val2 = $value_pair[1]; - $outputstr = $outputstr . " $val2 => '$val1',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . "?>\n"; -file_put_contents($prods_genque_keywd_file, $outputstr); diff --git a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsGenQueryNum.php b/apps/files_external/3rdparty/irodsphp/prods/src/setRodsGenQueryNum.php deleted file mode 100644 index 0be297826e..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/src/setRodsGenQueryNum.php +++ /dev/null @@ -1,61 +0,0 @@ - '$val2',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . '$GLOBALS[\'PRODS_GENQUE_NUMS_REV\']=array(' . "\n"; -foreach ($value_pairs as $value_pair) { - $val1 = $value_pair[0]; - $val2 = $value_pair[1]; - $outputstr = $outputstr . " '$val2' => '$val1',\n"; -} -$outputstr = $outputstr . ");\n"; - -$outputstr = $outputstr . "?>\n"; -file_put_contents($prods_genque_num_file, $outputstr); diff --git a/apps/files_external/3rdparty/irodsphp/prods/utilities/exif2meta.php b/apps/files_external/3rdparty/irodsphp/prods/utilities/exif2meta.php deleted file mode 100644 index 9ee9495f10..0000000000 --- a/apps/files_external/3rdparty/irodsphp/prods/utilities/exif2meta.php +++ /dev/null @@ -1,145 +0,0 @@ -getMeta(); - $metaalreadyset = false; - foreach ($metas as $meta) { - if ($meta->name == 'EXIF.ExifVersion') { - $metaalreadyset = true; - break; - } - } - - if ($metaalreadyset === true) { - $time = '[' . date('c') . ']'; - echo "$time 0: metadata already set for '$target_file'\n"; - exit(0); - } - - // download file from irods to tmp - $localfile = '/tmp/' . basename($target_file); - if (file_exists($localfile)) - unlink($localfile); - $irodsfile->open("r"); - $str = ''; - while ((($buffer = $irodsfile->read(1024 * 1024)) != NULL) && - (connection_status() == 0)) { - $str = $str . $buffer; - } - $irodsfile->close(); - file_put_contents($localfile, $str); - - extactExif($localfile, $irodsfile); - - if (file_exists($localfile)) - unlink($localfile); - - $time = '[' . date('c') . ']'; - echo "$time 0: '$target_file' processed!\n"; - exit(0); - -} catch (Exception $e) { - - if (file_exists($localfile)) - unlink($localfile); - - $time = '[' . date('c') . ']'; - echo "$time " . $e->getCode() . ": " . "$e"; - exit(-1); -} - - -function extactExif($localfile, $remoteRODSfile) -{ - $exif = exif_read_data($localfile, 'EXIF'); - if ($exif === false) return; - - foreach ($exif as $name => $val) { - - // replace ascii char that can't be displayed, which causes problem in irods - if ((!is_array($val)) && (is_string($val)) && - ((ord($val[0]) < 32) || (ord($val[0]) > 126)) && - ($name != 'UserComment') - ) { - $val = '__undefined__'; - } - - if ($name == 'THUMBNAIL') { - foreach ($val as $tname => $tval) - $remoteRODSfile->addMeta(new RODSMeta( - 'EXIF.THUMBNAIL.' . $tname, $tval, '')); - } else - if ($name == 'COMPUTED') { - foreach ($val as $cname => $cval) { - if ($cname == 'html') { - //skip html tag, because there is a irods server bug that corrupting string with - //double quotes: 'COMPUTED.html: width="3264" height="2448"' - } else - $remoteRODSfile->addMeta(new RODSMeta( - 'EXIF.COMPUTED.' . $cname, $cval, '')); - } - } else - if ($name == 'MakerNote') { - //skip makernote - } else - if ($name == 'ComponentsConfiguration') { - //skip ComponentsConfiguration, because there is a irods server bug that corrupting string with - - } else - if ($name == 'UserComment') { - if (($start = strpos($val, 'GCM_TAG')) !== false) { - $str = substr($val, $start + strlen('GCM_TAG')); - $gcm_tokens = explode(chr(0), $str); - $gcm_counter = 0; - foreach ($gcm_tokens as $gcm_tag) { - if ((strlen($gcm_tag) > 0) && (preg_match('/^[' . chr(32) . '-' . chr(126) . ']+$/', $gcm_tag))) { - $remoteRODSfile->addMeta(new RODSMeta( - 'EXIF.UserComment' . $gcm_counter++, $gcm_tag, '')); - } - } - } else { - if (strlen($val) < 1) - $str = ' '; - //replace no displable char - $str = preg_replace('/[^' . chr(32) . '-' . chr(126) . ']+/', ' ', $val); - $remoteRODSfile->addMeta(new RODSMeta( - 'EXIF.UserComment', $str, '')); - } - } else - if (is_array($val)) { - foreach ($val as $cname => $cval) { - $remoteRODSfile->addMeta(new RODSMeta( - "EXIF.$name." . $cname, $cval, '')); - } - } else - $remoteRODSfile->addMeta(new RODSMeta( - 'EXIF.' . $name, $val, '')); - } -} - -?> diff --git a/apps/files_external/3rdparty/irodsphp/release_notes.txt b/apps/files_external/3rdparty/irodsphp/release_notes.txt deleted file mode 100644 index 9d109faf84..0000000000 --- a/apps/files_external/3rdparty/irodsphp/release_notes.txt +++ /dev/null @@ -1,14 +0,0 @@ -*'''Project''': iRODS PHP Library PRODS and PRODS Web Browser -*'''Date''': 06/04/2013 -*'''Release Version''': 3.3.0-beta1 -*'''git tag''': 3.3.0-beta1 - -==News== - -The PRODS PHP Web Browser is also included in this project, and remains supported. Note that the PHP Web Browser functionality has been subsumed by the idrop-web browser and idrop-swing client. - -Please go to [[https://code.renci.org/gf/project/irodsphp/] for the latest news and info. - -Note that the git repository is now the canonical version of the PHP code. The code in the iRODS SVN server is deprecated and will be taken down at the 3.0.0 release point. There may be other versions in Google Code and other places, but these should be considered obsolete. - -Please review release notes in sub projects for details diff --git a/apps/files_external/3rdparty/phpseclib/LICENSE b/apps/files_external/3rdparty/phpseclib/LICENSE index 6ecd9b9bec..75f6b2045c 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 e90b12f4a6..de52823166 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 79c92b52e4..70f4f7c36e 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 0000000000..1b5ff07e48 --- /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 81fa2feab6..cf8c050a59 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 7c650ca729..f08529b902 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 c8ef67e8f7..b352e7c468 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 8b04210659..fcbf01993a 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 2189724198..b156169d68 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 5e0ca88c8f..de22d631a1 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 f6a9eae2fb..d062be2573 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 92ebfdf723..feb887c703 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 8532aab5a5..977ec79726 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 c63e0ff7e3..42531516cf 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 4030c6c9fb..21318209fe 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 6342298d1a..9be5fd1099 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 f7ac85536f..0e0004ce27 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 9f481fc3cc..67d1f6dc79 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 0b4e291361..9e7b0b3b96 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 e40433de5b..1b4ea675fc 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 88180cac67..4cfa357009 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 5356ffbf77..68d944f9f3 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 0572c5c402..48b79b3ef7 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 83d5980d00..0a6aa90828 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; + 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; - // 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(); - 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 dad0369723..2fddb68a9b 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 6baa566102..2b8b52f9f7 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 622942b052..e325506fa1 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,7 +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) # 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 @@ -43,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) { @@ -74,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) { + function client ($params, $purl, $regexp = NULL) { - 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' - ); + if ($regexp === NULL) $regexp = smb::$regexp; if (SMB4PHP_AUTHMODE == 'env') { putenv("USER={$purl['user']}%{$purl['pass']}"); @@ -238,17 +245,10 @@ class smb { trigger_error ("url_stat(): list failed for host '{$pu['host']}'", E_USER_WARNING); break; case 'share': - if ($o = smb::look ($pu)) { - $found = FALSE; - $lshare = strtolower ($pu['share']); # fix by Eric Leung - foreach ($o['disk'] as $s) if ($lshare == strtolower($s)) { - $found = TRUE; - $stat = stat ("/tmp"); - break; - } - if (! $found) - trigger_error ("url_stat(): disk resource '{$lshare}' not found in '{$pu['host']}'", E_USER_WARNING); - } + if (smb::execute("ls", $pu)) + $stat = stat ("/tmp"); + else + trigger_error ("url_stat(): disk resource '{$pu['share']}' not found in '{$pu['host']}'", E_USER_WARNING); break; case 'path': if ($o = smb::execute ('dir "'.$pu['path'].'"', $pu)) { diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php index 5b1cd86a17..003665486f 100644 --- a/apps/files_external/appinfo/app.php +++ b/apps/files_external/appinfo/app.php @@ -1,10 +1,12 @@ + * Copyright (c) 2014 Robin McCorkell * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ +$l = \OC_L10N::get('files_external'); OC::$CLASSPATH['OC\Files\Storage\StreamWrapper'] = 'files_external/lib/streamwrapper.php'; OC::$CLASSPATH['OC\Files\Storage\FTP'] = 'files_external/lib/ftp.php'; @@ -13,10 +15,10 @@ 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'; -OC::$CLASSPATH['OC\Files\Storage\iRODS'] = 'files_external/lib/irods.php'; OC::$CLASSPATH['OC_Mount_Config'] = 'files_external/lib/config.php'; OCP\App::registerAdmin('files_external', 'settings'); @@ -25,5 +27,128 @@ if (OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes') == ' } // connecting hooks -OCP\Util::connectHook( 'OC_User', 'post_login', 'OC\Files\Storage\iRODS', 'login' ); +OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\OC_Mount_Config', 'initMountPointsHook'); +OCP\Util::connectHook('OC_User', 'post_login', 'OC\Files\Storage\SMB_OC', 'login'); +OC_Mount_Config::registerBackend('\OC\Files\Storage\Local', array( + 'backend' => (string)$l->t('Local'), + 'configuration' => array( + 'datadir' => (string)$l->t('Location')))); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\AmazonS3', array( + 'backend' => (string)$l->t('Amazon S3'), + 'configuration' => array( + 'key' => (string)$l->t('Key'), + 'secret' => '*'.$l->t('Secret'), + 'bucket' => (string)$l->t('Bucket')), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\AmazonS3', array( + 'backend' => (string)$l->t('Amazon S3 and compliant'), + 'configuration' => array( + 'key' => (string)$l->t('Access Key'), + 'secret' => '*'.$l->t('Secret Key'), + 'bucket' => (string)$l->t('Bucket'), + 'hostname' => '&'.$l->t('Hostname (optional)'), + 'port' => '&'.$l->t('Port (optional)'), + 'region' => '&'.$l->t('Region (optional)'), + 'use_ssl' => '!'.$l->t('Enable SSL'), + 'use_path_style' => '!'.$l->t('Enable Path Style')), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\Dropbox', array( + 'backend' => 'Dropbox', + 'configuration' => array( + 'configured' => '#configured', + 'app_key' => (string)$l->t('App key'), + 'app_secret' => '*'.$l->t('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' => (string)$l->t('URL'), + 'user' => (string)$l->t('Username'), + 'password' => '*'.$l->t('Password'), + 'root' => '&'.$l->t('Root'), + 'secure' => '!'.$l->t('Secure ftps://')), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\Google', array( + 'backend' => 'Google Drive', + 'configuration' => array( + 'configured' => '#configured', + 'client_id' => (string)$l->t('Client ID'), + 'client_secret' => '*'.$l->t('Client secret'), + 'token' => '#token'), + 'custom' => 'google', + 'has_dependencies' => true)); + + +OC_Mount_Config::registerBackend('\OC\Files\Storage\Swift', array( + 'backend' => (string)$l->t('OpenStack Object Storage'), + 'configuration' => array( + 'user' => (string)$l->t('Username (required)'), + 'bucket' => (string)$l->t('Bucket (required)'), + 'region' => '&'.$l->t('Region (optional for OpenStack Object Storage)'), + 'key' => '*'.$l->t('API Key (required for Rackspace Cloud Files)'), + 'tenant' => '&'.$l->t('Tenantname (required for OpenStack Object Storage)'), + 'password' => '*'.$l->t('Password (required for OpenStack Object Storage)'), + 'service_name' => '&'.$l->t('Service Name (required for OpenStack Object Storage)'), + 'url' => '&'.$l->t('URL of identity endpoint (required for OpenStack Object Storage)'), + 'timeout' => '&'.$l->t('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' => (string)$l->t('URL'), + 'user' => (string)$l->t('Username'), + 'password' => '*'.$l->t('Password'), + 'share' => (string)$l->t('Share'), + 'root' => '&'.$l->t('Root')), + 'has_dependencies' => true)); + + OC_Mount_Config::registerBackend('\OC\Files\Storage\SMB_OC', array( + 'backend' => (string)$l->t('SMB / CIFS using OC login'), + 'configuration' => array( + 'host' => (string)$l->t('URL'), + 'username_as_share' => '!'.$l->t('Username as share'), + 'share' => '&'.$l->t('Share'), + 'root' => '&'.$l->t('Root')), + 'has_dependencies' => true)); +} + +OC_Mount_Config::registerBackend('\OC\Files\Storage\DAV', array( + 'backend' => 'WebDAV', + 'configuration' => array( + 'host' => (string)$l->t('URL'), + 'user' => (string)$l->t('Username'), + 'password' => '*'.$l->t('Password'), + 'root' => '&'.$l->t('Root'), + 'secure' => '!'.$l->t('Secure https://')), + 'has_dependencies' => true)); + +OC_Mount_Config::registerBackend('\OC\Files\Storage\OwnCloud', array( + 'backend' => 'ownCloud', + 'configuration' => array( + 'host' => (string)$l->t('URL'), + 'user' => (string)$l->t('Username'), + 'password' => '*'.$l->t('Password'), + 'root' => '&'.$l->t('Remote subfolder'), + 'secure' => '!'.$l->t('Secure https://')))); + + +OC_Mount_Config::registerBackend('\OC\Files\Storage\SFTP', array( + 'backend' => 'SFTP', + 'configuration' => array( + 'host' => (string)$l->t('URL'), + 'user' => (string)$l->t('Username'), + 'password' => '*'.$l->t('Password'), + 'root' => '&'.$l->t('Root')))); diff --git a/apps/files_external/css/settings.css b/apps/files_external/css/settings.css index 11aeb10184..ee2c0aae64 100644 --- a/apps/files_external/css/settings.css +++ b/apps/files_external/css/settings.css @@ -4,16 +4,9 @@ td.status > span { width: 16px; vertical-align: text-bottom; } -span.success { - background: #37ce02; - border-radius: 8px; -} -span.error { - background: #ce3702; -} td.mountPoint, td.backend { width:160px; } -td.remove>img { visibility:hidden; padding-top:13px; } +td.remove>img { visibility:hidden; padding-top:7px; } tr:hover>td.remove>img { visibility:visible; cursor:pointer; } #addMountPoint>td { border:none; } #addMountPoint>td.applicable { visibility:hidden; } @@ -22,3 +15,8 @@ tr:hover>td.remove>img { visibility:visible; cursor:pointer; } #externalStorage label > input[type="checkbox"] { margin-right: 3px; } + +#externalStorage td.applicable div.chzn-container { + position: relative; + top: 3px; +} diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 895f97bd2c..00793a614c 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) { @@ -264,7 +269,7 @@ $(document).ready(function() { OC.MountConfig.saveStorage($(this).parent().parent()); }); - $('#sslCertificate').on('click', 'td.remove>img', function() { + $('#sslCertificate').on('click', 'td.remove>img', function() { var $tr = $(this).parent().parent(); var row = this.parentNode.parentNode; $.post(OC.filePath('files_external', 'ajax', 'removeRootCertificate.php'), {cert: row.id}); @@ -302,13 +307,23 @@ $(document).ready(function() { }); $('#allowUserMounting').bind('change', function() { + OC.msg.startSaving('#userMountingMsg'); if (this.checked) { OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'yes'); + $('#userMountingBackups').removeClass('hidden'); } else { OC.AppConfig.setValue('files_external', 'allow_user_mounting', 'no'); + $('#userMountingBackups').addClass('hidden'); } + OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}}); }); + $('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() { + OC.msg.startSaving('#userMountingMsg'); + var user_mounting_backends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get(); + OC.AppConfig.setValue('files_external', 'user_mounting_backends', user_mounting_backends.join()); + OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('settings', 'Saved')}}); + }); }); })(); diff --git a/apps/files_external/l10n/af_ZA.php b/apps/files_external/l10n/af_ZA.php index 261c44310f..f0c9c5211b 100644 --- a/apps/files_external/l10n/af_ZA.php +++ b/apps/files_external/l10n/af_ZA.php @@ -1,5 +1,8 @@ "Gebruikersnaam", +"Password" => "Wagwoord", +"Share" => "Deel", "Users" => "Gebruikers" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/ar.php b/apps/files_external/l10n/ar.php index 338526d2af..5bef941c19 100644 --- a/apps/files_external/l10n/ar.php +++ b/apps/files_external/l10n/ar.php @@ -1,5 +1,11 @@ "المكان", +"URL" => "عنوان الموقع", +"Username" => "إسم المستخدم", +"Password" => "كلمة السر", +"Share" => "شارك", +"Saved" => "حفظ", "Folder name" => "اسم المجلد", "Options" => "خيارات", "All Users" => "كل المستخدمين", diff --git a/apps/files_external/l10n/ast.php b/apps/files_external/l10n/ast.php new file mode 100644 index 0000000000..add4981915 --- /dev/null +++ b/apps/files_external/l10n/ast.php @@ -0,0 +1,17 @@ + "Llocal", +"Location" => "Llocalización", +"URL" => "URL", +"Username" => "Nome d'usuariu", +"Password" => "Contraseña", +"Share" => "Compartir", +"Saved" => "Guardáu", +"Folder name" => "Nome de la carpeta", +"Configuration" => "Configuración", +"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 17665d2228..0969184383 100644 --- a/apps/files_external/l10n/bg_BG.php +++ b/apps/files_external/l10n/bg_BG.php @@ -1,19 +1,21 @@ "Място", +"URL" => "Уеб адрес", +"Username" => "Потребител", +"Password" => "Парола", +"Share" => "Споделяне", "Access granted" => "Достъпът е даден", "Grant access" => "Даване на достъп", "External Storage" => "Външно хранилище", "Folder name" => "Име на папката", "Configuration" => "Конфигурация", "Options" => "Опции", -"Applicable" => "Приложимо", -"None set" => "Няма избрано", "All Users" => "Всички потребители", "Groups" => "Групи", "Users" => "Потребители", "Delete" => "Изтриване", "Enable User External Storage" => "Вкл. на поддръжка за външно потр. хранилище", -"Allow users to mount their own external storage" => "Позволено е на потребителите да ползват тяхно лично външно хранилище", "SSL root certificates" => "SSL основни сертификати", "Import Root Certificate" => "Импортиране на основен сертификат" ); diff --git a/apps/files_external/l10n/bn_BD.php b/apps/files_external/l10n/bn_BD.php index 0591dbba55..3b1978a568 100644 --- a/apps/files_external/l10n/bn_BD.php +++ b/apps/files_external/l10n/bn_BD.php @@ -1,5 +1,10 @@ "াবস্থান", +"URL" => "URL", +"Username" => "ব্যবহারকারী", +"Password" => "কূটশব্দ", +"Share" => "ভাগাভাগি কর", "Access granted" => "অধিগমনের অনুমতি প্রদান করা হলো", "Error configuring Dropbox storage" => "Dropbox সংরক্ষণাগার নির্ধারণ করতে সমস্যা ", "Grant access" => "অধিগমনের অনুমতি প্রদান কর", @@ -8,14 +13,11 @@ $TRANSLATIONS = array( "External Storage" => "বাহ্যিক সংরক্ষণাগার", "Configuration" => "কনফিগারেসন", "Options" => "বিকল্পসমূহ", -"Applicable" => "প্রযোজ্য", -"None set" => "কোনটিই নির্ধারণ করা হয় নি", "All Users" => "সমস্ত ব্যবহারকারী", "Groups" => "গোষ্ঠীসমূহ", "Users" => "ব্যবহারকারী", "Delete" => "মুছে", "Enable User External Storage" => "ব্যবহারকারীর বাহ্যিক সংরক্ষণাগার সক্রিয় কর", -"Allow users to mount their own external storage" => "ব্যবহারকারীদেরকে তাদের নিজস্ব বাহ্যিক সংরক্ষনাগার সাউন্ট করতে অনুমোদন দাও", "SSL root certificates" => "SSL রুট সনদপত্র", "Import Root Certificate" => "রুট সনদপত্রটি আমদানি করুন" ); diff --git a/apps/files_external/l10n/bs.php b/apps/files_external/l10n/bs.php new file mode 100644 index 0000000000..304b2225e7 --- /dev/null +++ b/apps/files_external/l10n/bs.php @@ -0,0 +1,5 @@ + "Podijeli" +); +$PLURAL_FORMS = "nplurals=3; 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_external/l10n/ca.php b/apps/files_external/l10n/ca.php index c1d6ec077b..e49f26c353 100644 --- a/apps/files_external/l10n/ca.php +++ b/apps/files_external/l10n/ca.php @@ -1,27 +1,36 @@ "Local", +"Location" => "Ubicació", +"URL" => "URL", +"Username" => "Nom d'usuari", +"Password" => "Contrasenya", +"Share" => "Comparteix", "Access granted" => "S'ha concedit l'accés", "Error configuring Dropbox storage" => "Error en configurar l'emmagatzemament Dropbox", "Grant access" => "Concedeix accés", "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", -"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.", +"Saved" => "Desat", +"Note: " => "Nota: ", +" and " => "i", +"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 suport cURL no està activat o instal·lat a PHP. No es pot muntar %s. Demaneu a l'administrador del sistema que l'instal·li.", +"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 suport FTP per PHP no està activat o no està instal·lat. No es pot muntar %s. Demaneu a l'administrador del sistema que l'instal·li.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: %s no està instal·lat. No es pot muntar %s. Demaneu a l'administrador del sistema que l'instal·li.", "External Storage" => "Emmagatzemament extern", "Folder name" => "Nom de la carpeta", "External storage" => "Emmagatzemament extern", "Configuration" => "Configuració", "Options" => "Options", -"Applicable" => "Aplicable", +"Available for" => "Disponible per", "Add storage" => "Afegeix emmagatzemament", -"None set" => "Cap d'establert", +"No user or group" => "Sense usuaris o grups", "All Users" => "Tots els usuaris", "Groups" => "Grups", "Users" => "Usuaris", "Delete" => "Esborra", "Enable User External Storage" => "Habilita l'emmagatzemament extern d'usuari", -"Allow users to mount their own external storage" => "Permet als usuaris muntar el seu emmagatzemament extern propi", +"Allow users to mount the following external storage" => "Permet als usuaris muntar els dispositius externs següents", "SSL root certificates" => "Certificats SSL root", "Import Root Certificate" => "Importa certificat root" ); diff --git a/apps/files_external/l10n/cs_CZ.php b/apps/files_external/l10n/cs_CZ.php index a574e0506c..e953e19a9d 100644 --- a/apps/files_external/l10n/cs_CZ.php +++ b/apps/files_external/l10n/cs_CZ.php @@ -1,27 +1,57 @@ "Místní", +"Location" => "Umístění", +"Amazon S3" => "Amazon S3", +"Key" => "Klíč", +"Secret" => "Tajemství", +"Access Key" => "Přístupový klíč", +"Secret Key" => "Tajný klíč", +"Hostname (optional)" => "Hostname (nepovinný)", +"Port (optional)" => "Port (nepovinný)", +"Region (optional)" => "Region (nepovinný)", +"Enable SSL" => "Povolit SSL", +"App key" => "Klíč aplikace", +"App secret" => "Tajemství aplikace", +"URL" => "URL", +"Username" => "Uživatelské jméno", +"Password" => "Heslo", +"Root" => "Root", +"Secure ftps://" => "Zabezpečené ftps://", +"Username (required)" => "Uživatelské jméno (nutné)", +"Region (optional for OpenStack Object Storage)" => "Region (nepovinný pro OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Heslo (vyžadováno pro OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Vypršení HTTP požadavků v sekundách (nepovinné)", +"Share" => "Sdílet", +"SMB / CIFS using OC login" => "SMB / CIFS za použití OC loginu", +"Username as share" => "Uživatelské jméno jako sdílený adresář", +"Secure https://" => "Zabezpečené https://", +"Remote subfolder" => "Vzdálený podadresář", "Access granted" => "Přístup povolen", "Error configuring Dropbox storage" => "Chyba při nastavení úložiště Dropbox", "Grant access" => "Povolit přístup", "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", -"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.", +"Saved" => "Uloženo", +"Note: " => "Poznámka:", +" and " => "a", +"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." => "Poznámka: cURL podpora v PHP není povolena nebo nainstalována. Není možné připojení %s. Prosím požádejte svého správce systému ať ji nainstaluje.", +"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." => "Poznámka: FTP podpora v PHP není povolena nebo nainstalována. Není možné připojení %s. Prosím požádejte svého správce systému ať ji nainstaluje.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Poznámka: \"%s\" není instalováno. Není možné připojení %s. Prosím požádejte svého správce systému o instalaci.", "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", +"Available for" => "Dostupné pro", "Add storage" => "Přidat úložiště", -"None set" => "Nenastaveno", +"No user or group" => "Žádný uživatel nebo skupina", "All Users" => "Všichni uživatelé", "Groups" => "Skupiny", "Users" => "Uživatelé", "Delete" => "Smazat", "Enable User External Storage" => "Zapnout externí uživatelské úložiště", -"Allow users to mount their own external storage" => "Povolit uživatelům připojení jejich vlastních externích úložišť", +"Allow users to mount the following external storage" => "Povolit uživatelů připojit následující externí úložiště", "SSL root certificates" => "Kořenové certifikáty SSL", "Import Root Certificate" => "Importovat kořenového certifikátu" ); diff --git a/apps/files_external/l10n/cy_GB.php b/apps/files_external/l10n/cy_GB.php index 33992789cb..9b5d97a48a 100644 --- a/apps/files_external/l10n/cy_GB.php +++ b/apps/files_external/l10n/cy_GB.php @@ -1,5 +1,10 @@ "Lleoliad", +"URL" => "URL", +"Username" => "Enw defnyddiwr", +"Password" => "Cyfrinair", +"Share" => "Rhannu", "Groups" => "Grwpiau", "Users" => "Defnyddwyr", "Delete" => "Dileu" diff --git a/apps/files_external/l10n/da.php b/apps/files_external/l10n/da.php index 3a25142b36..a0e8510789 100644 --- a/apps/files_external/l10n/da.php +++ b/apps/files_external/l10n/da.php @@ -1,27 +1,43 @@ "Lokal", +"Location" => "Placering", +"Amazon S3" => "Amazon S3", +"Key" => "Nøgle", +"Secret" => "Hemmelighed", +"Secret Key" => "Hemmelig Nøgle ", +"URL" => "URL", +"Username" => "Brugernavn", +"Password" => "Kodeord", +"Root" => "Root", +"Secure ftps://" => "Sikker ftps://", +"Client ID" => "Klient ID", +"Client secret" => "Klient hemmelighed", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Share" => "Del", +"Secure https://" => "Sikker https://", "Access granted" => "Adgang godkendt", "Error configuring Dropbox storage" => "Fejl ved konfiguration af Dropbox plads", "Grant access" => "Godkend adgang", "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", -"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. ", +"Saved" => "Gemt", +"Note: " => "Note: ", +" and " => "og", "External Storage" => "Ekstern opbevaring", "Folder name" => "Mappenavn", "External storage" => "Eksternt lager", "Configuration" => "Opsætning", "Options" => "Valgmuligheder", -"Applicable" => "Kan anvendes", +"Available for" => "Tilgængelig for", "Add storage" => "Tilføj lager", -"None set" => "Ingen sat", +"No user or group" => "Ingen bruger eller gruppe", "All Users" => "Alle brugere", "Groups" => "Grupper", "Users" => "Brugere", "Delete" => "Slet", "Enable User External Storage" => "Aktiver ekstern opbevaring for brugere", -"Allow users to mount their own external storage" => "Tillad brugere at montere deres egne eksterne opbevaring", +"Allow users to mount the following external storage" => "Tillad brugere at montere følgende som eksternt lager", "SSL root certificates" => "SSL-rodcertifikater", "Import Root Certificate" => "Importer rodcertifikat" ); diff --git a/apps/files_external/l10n/de.php b/apps/files_external/l10n/de.php index b2c72f7688..c41cef968f 100644 --- a/apps/files_external/l10n/de.php +++ b/apps/files_external/l10n/de.php @@ -1,27 +1,68 @@ "Lokal", +"Location" => "Ort", +"Amazon S3" => "Amazon S3", +"Key" => "Schlüssel", +"Secret" => "Geheime Zeichenkette", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 und Kompatible", +"Access Key" => "Zugriffsschlüssel", +"Secret Key" => "Sicherheitssschlüssel", +"Hostname (optional)" => "Host-Name (Optional)", +"Port (optional)" => "Port (Optional)", +"Region (optional)" => "Region (Optional)", +"Enable SSL" => "SSL aktivieren", +"Enable Path Style" => "Pfad-Stil aktivieren", +"App key" => "App-Schlüssel", +"App secret" => "Geheime Zeichenkette der App", +"URL" => "URL", +"Username" => "Benutzername", +"Password" => "Passwort", +"Root" => "Root", +"Secure ftps://" => "Sicherer FTPS://", +"Client ID" => "Client-ID", +"Client secret" => "Geheime Zeichenkette des Client", +"OpenStack Object Storage" => "Openstack-Objektspeicher", +"Username (required)" => "Benutzername (Erforderlich)", +"Bucket (required)" => "Bucket (Erforderlich)", +"Region (optional for OpenStack Object Storage)" => "Region (Optional für Openstack-Objektspeicher)", +"API Key (required for Rackspace Cloud Files)" => "API-Schlüssel (Erforderlich für Rackspace Cloud-Dateien)", +"Tenantname (required for OpenStack Object Storage)" => "Mietername (Erforderlich für Openstack-Objektspeicher)", +"Password (required for OpenStack Object Storage)" => "Passwort (Erforderlich für Openstack-Objektspeicher)", +"Service Name (required for OpenStack Object Storage)" => "Name der Dienstleistung (Erforderlich für Openstack-Objektspeicher)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL des Identitätsendpunktes (Erforderlich für Openstack-Objektspeicher)", +"Timeout of HTTP requests in seconds (optional)" => "Zeitüberschreitung von HTTP-Anfragen in Sekunden (Optional)", +"Share" => "Teilen", +"SMB / CIFS using OC login" => "´", +"Username as share" => "Benutzername als Freigabe", +"Secure https://" => "Sicherer HTTPS://", +"Remote subfolder" => "Remote-Unterordner:", "Access granted" => "Zugriff gestattet", "Error configuring Dropbox storage" => "Fehler beim Einrichten von Dropbox", "Grant access" => "Zugriff gestatten", "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", -"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. ", +"Saved" => "Gespeichert", +"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", "Delete" => "Löschen", "Enable User External Storage" => "Externen Speicher für Benutzer aktivieren", -"Allow users to mount their own external storage" => "Erlaubt Benutzern ihre eigenen externen Speicher einzubinden", +"Allow users to mount the following external storage" => "Erlaube es Benutzern, den folgenden externen Speicher einzubinden", "SSL root certificates" => "SSL-Root-Zertifikate", "Import Root Certificate" => "Root-Zertifikate importieren" ); diff --git a/apps/files_external/l10n/de_AT.php b/apps/files_external/l10n/de_AT.php new file mode 100644 index 0000000000..21004505e5 --- /dev/null +++ b/apps/files_external/l10n/de_AT.php @@ -0,0 +1,8 @@ + "Ort", +"Password" => "Passwort", +"Share" => "Freigeben", +"Delete" => "Löschen" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/de_CH.php b/apps/files_external/l10n/de_CH.php index 85e2f2d91f..6d7366fe28 100644 --- a/apps/files_external/l10n/de_CH.php +++ b/apps/files_external/l10n/de_CH.php @@ -1,27 +1,26 @@ "Ort", +"URL" => "URL", +"Username" => "Benutzername", +"Password" => "Passwort", +"Share" => "Freigeben", "Access granted" => "Zugriff gestattet", "Error configuring Dropbox storage" => "Fehler beim Einrichten von Dropbox", "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", "Delete" => "Löschen", "Enable User External Storage" => "Externen Speicher für Benutzer aktivieren", -"Allow users to mount their own external storage" => "Erlaubt Benutzern, ihre eigenen externen Speicher einzubinden", "SSL root certificates" => "SSL-Root-Zertifikate", "Import Root Certificate" => "Root-Zertifikate importieren" ); diff --git a/apps/files_external/l10n/de_DE.php b/apps/files_external/l10n/de_DE.php index 8f6a25cb52..1119a0f875 100644 --- a/apps/files_external/l10n/de_DE.php +++ b/apps/files_external/l10n/de_DE.php @@ -1,27 +1,68 @@ "Lokal", +"Location" => "Ort", +"Amazon S3" => "Amazon S3", +"Key" => "Schlüssel", +"Secret" => "Geheime Zeichenkette", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 und Kompatible", +"Access Key" => "Zugriffsschlüssel", +"Secret Key" => "Sicherheitsschlüssel", +"Hostname (optional)" => "Host-Name (Optional)", +"Port (optional)" => "Port (Optional)", +"Region (optional)" => "Region (Optional)", +"Enable SSL" => "SSL aktivieren", +"Enable Path Style" => "Pfad-Stil aktivieren", +"App key" => "App-Schlüssel", +"App secret" => "Geheime Zeichenkette der App", +"URL" => "URL", +"Username" => "Benutzername", +"Password" => "Passwort", +"Root" => "Root", +"Secure ftps://" => "Sicherer FTPS://", +"Client ID" => "Client-ID", +"Client secret" => "Geheime Zeichenkette des Client", +"OpenStack Object Storage" => "Openstack-Objektspeicher", +"Username (required)" => "Benutzername (Erforderlich)", +"Bucket (required)" => "Bucket (Erforderlich)", +"Region (optional for OpenStack Object Storage)" => "Region (Optional für Openstack-Objektspeicher)", +"API Key (required for Rackspace Cloud Files)" => "API-Schlüssel (Erforderlich für Rackspace Cloud-Dateien)", +"Tenantname (required for OpenStack Object Storage)" => "Mietername (Erforderlich für Openstack-Objektspeicher)", +"Password (required for OpenStack Object Storage)" => "Passwort (Erforderlich für Openstack-Objektspeicher)", +"Service Name (required for OpenStack Object Storage)" => "Name der Dienstleistung (Erforderlich für Openstack-Objektspeicher)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL des Identitätsendpunktes (Erforderlich für Openstack-Objektspeicher)", +"Timeout of HTTP requests in seconds (optional)" => "Zeitüberschreitung von HTTP-Anfragen in Sekunden (Optional)", +"Share" => "Teilen", +"SMB / CIFS using OC login" => "Zeitüberschreitung von HTTP-Anfragen in Sekunden (Optional)", +"Username as share" => "Benutzername als Freigabe", +"Secure https://" => "Sicherer HTTPS://", +"Remote subfolder" => "Remote-Unterordner:", "Access granted" => "Zugriff gestattet", "Error configuring Dropbox storage" => "Fehler beim Einrichten von Dropbox", "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.", +"Saved" => "Gespeichert", +"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", "Delete" => "Löschen", "Enable User External Storage" => "Externen Speicher für Benutzer aktivieren", -"Allow users to mount their own external storage" => "Erlaubt Benutzern, ihre eigenen externen Speicher einzubinden", +"Allow users to mount the following external storage" => "Erlauben Sie Benutzern, folgende externe Speicher einzubinden", "SSL root certificates" => "SSL-Root-Zertifikate", "Import Root Certificate" => "Root-Zertifikate importieren" ); diff --git a/apps/files_external/l10n/el.php b/apps/files_external/l10n/el.php index 0161c0901d..351468a36d 100644 --- a/apps/files_external/l10n/el.php +++ b/apps/files_external/l10n/el.php @@ -1,27 +1,32 @@ "Τοπικός", +"Location" => "Τοποθεσία", +"URL" => "URL", +"Username" => "Όνομα χρήστη", +"Password" => "Κωδικός πρόσβασης", +"Username (required)" => "Όνομα χρήστη (απαιτείται)", +"Share" => "Διαμοιράστε", "Access granted" => "Προσβαση παρασχέθηκε", "Error configuring Dropbox storage" => "Σφάλμα ρυθμίζωντας αποθήκευση Dropbox ", "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" => "Αποθηκεύτηκαν", +" and " => "και", "External Storage" => "Εξωτερικό Αποθηκευτικό Μέσο", "Folder name" => "Όνομα φακέλου", "External storage" => "Εξωτερική αποθήκευση", "Configuration" => "Ρυθμίσεις", "Options" => "Επιλογές", -"Applicable" => "Εφαρμόσιμο", "Add storage" => "Προσθηκη αποθηκευσης", -"None set" => "Κανένα επιλεγμένο", +"No user or group" => "Μη διαθέσιμος χρήστης ή ομάδα", "All Users" => "Όλοι οι Χρήστες", "Groups" => "Ομάδες", "Users" => "Χρήστες", "Delete" => "Διαγραφή", "Enable User External Storage" => "Ενεργοποίηση Εξωτερικού Αποθηκευτικού Χώρου Χρήστη", -"Allow users to mount their own 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@pirate.php b/apps/files_external/l10n/en@pirate.php new file mode 100644 index 0000000000..ab628e1717 --- /dev/null +++ b/apps/files_external/l10n/en@pirate.php @@ -0,0 +1,5 @@ + "Secret Code" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/en_GB.php b/apps/files_external/l10n/en_GB.php index 8adca794dd..5a0e2456ac 100644 --- a/apps/files_external/l10n/en_GB.php +++ b/apps/files_external/l10n/en_GB.php @@ -1,27 +1,68 @@ "Local", +"Location" => "Location", +"Amazon S3" => "Amazon S3", +"Key" => "Key", +"Secret" => "Secret", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 and compliant", +"Access Key" => "Access Key", +"Secret Key" => "Secret Key", +"Hostname (optional)" => "Hostname (optional)", +"Port (optional)" => "Port (optional)", +"Region (optional)" => "Region (optional)", +"Enable SSL" => "Enable SSL", +"Enable Path Style" => "Enable Path Style", +"App key" => "App key", +"App secret" => "App secret", +"URL" => "URL", +"Username" => "Username", +"Password" => "Password", +"Root" => "Root", +"Secure ftps://" => "Secure ftps://", +"Client ID" => "Client ID", +"Client secret" => "Client secret", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "Username (required)", +"Bucket (required)" => "Bucket (required)", +"Region (optional for OpenStack Object Storage)" => "Region (optional for OpenStack Object Storage)", +"API Key (required for Rackspace Cloud Files)" => "API Key (required for Rackspace Cloud Files)", +"Tenantname (required for OpenStack Object Storage)" => "Tenantname (required for OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Password (required for OpenStack Object Storage)", +"Service Name (required for OpenStack Object Storage)" => "Service Name (required for OpenStack Object Storage)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL of identity endpoint (required for OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Timeout of HTTP requests in seconds (optional)", +"Share" => "Share", +"SMB / CIFS using OC login" => "SMB / CIFS using OC login", +"Username as share" => "Username as share", +"Secure https://" => "Secure https://", +"Remote subfolder" => "Remote subfolder", "Access granted" => "Access granted", "Error configuring Dropbox storage" => "Error configuring Dropbox storage", "Grant access" => "Grant access", "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", -"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.", +"Saved" => "Saved", +"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", "Delete" => "Delete", "Enable User External Storage" => "Enable User External Storage", -"Allow users to mount their own external storage" => "Allow users to mount their own external storage", +"Allow users to mount the following external storage" => "Allow users to mount the following external storage", "SSL root certificates" => "SSL root certificates", "Import Root Certificate" => "Import Root Certificate" ); diff --git a/apps/files_external/l10n/eo.php b/apps/files_external/l10n/eo.php index 5697221cac..d8915b49b0 100644 --- a/apps/files_external/l10n/eo.php +++ b/apps/files_external/l10n/eo.php @@ -1,5 +1,10 @@ "Loko", +"URL" => "URL", +"Username" => "Uzantonomo", +"Password" => "Pasvorto", +"Share" => "Kunhavigi", "Access granted" => "Alirpermeso donita", "Error configuring Dropbox storage" => "Eraro dum agordado de la memorservo Dropbox", "Grant access" => "Doni alirpermeson", @@ -9,14 +14,11 @@ $TRANSLATIONS = array( "Folder name" => "Dosierujnomo", "Configuration" => "Agordo", "Options" => "Malneproj", -"Applicable" => "Aplikebla", -"None set" => "Nenio agordita", "All Users" => "Ĉiuj uzantoj", "Groups" => "Grupoj", "Users" => "Uzantoj", "Delete" => "Forigi", "Enable User External Storage" => "Kapabligi malenan memorilon de uzanto", -"Allow users to mount their own external storage" => "Permesi al uzantoj surmeti siajn proprajn malenajn memorilojn", "SSL root certificates" => "Radikaj SSL-atestoj", "Import Root Certificate" => "Enporti radikan ateston" ); diff --git a/apps/files_external/l10n/es.php b/apps/files_external/l10n/es.php index 5179d9329a..3c18b18057 100644 --- a/apps/files_external/l10n/es.php +++ b/apps/files_external/l10n/es.php @@ -1,27 +1,68 @@ "Local", +"Location" => "Ubicación", +"Amazon S3" => "Amazon S3", +"Key" => "Clave", +"Secret" => "Secreto", +"Bucket" => "Depósito", +"Amazon S3 and compliant" => "Amazon S3 y compatibilidad", +"Access Key" => "Clave de Acceso", +"Secret Key" => "Clave Secreta", +"Hostname (optional)" => "Nombre de Equipo (opcional)", +"Port (optional)" => "Puerto (opcional)", +"Region (optional)" => "Región (opcional)", +"Enable SSL" => "Habilitar SSL", +"Enable Path Style" => "Habilitar Estilo de Ruta", +"App key" => "App principal", +"App secret" => "App secreta", +"URL" => "URL", +"Username" => "Nombre de usuario", +"Password" => "Contraseña", +"Root" => "Raíz", +"Secure ftps://" => "Secure ftps://", +"Client ID" => "ID de Cliente", +"Client secret" => "Cliente secreto", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "Nombre de Usuario (requerido)", +"Bucket (required)" => "Depósito (requerido)", +"Region (optional for OpenStack Object Storage)" => "Región (opcional para OpenStack Object Storage)", +"API Key (required for Rackspace Cloud Files)" => "Clave API (requerida para Rackspace Cloud Files)", +"Tenantname (required for OpenStack Object Storage)" => "Nombre de Inquilino (requerido para OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Contraseña (requerida para OpenStack Object Storage)", +"Service Name (required for OpenStack Object Storage)" => "Nombre de Servicio (requerido para OpenStack Object Storage)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL de identidad de punto final (requerido para OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Tiempo de espera de peticiones HTTP en segundos (opcional)", +"Share" => "Compartir", +"SMB / CIFS using OC login" => "SMB / CIFS usando acceso OC", +"Username as share" => "Nombre de Usuario como compartir", +"Secure https://" => "Secure https://", +"Remote subfolder" => "Subcarpeta remota", "Access granted" => "Acceso concedido", "Error configuring Dropbox storage" => "Error configurando el almacenamiento de Dropbox", "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 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.", +"Saved" => "Guardado", +"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", "Delete" => "Eliminar", "Enable User External Storage" => "Habilitar almacenamiento externo de usuario", -"Allow users to mount their own external storage" => "Permitir a los usuarios montar su propio almacenamiento externo", +"Allow users to mount the following external storage" => "Permitir a los usuarios montar el siguiente almacenamiento externo", "SSL root certificates" => "Certificados raíz SSL", "Import Root Certificate" => "Importar certificado raíz" ); diff --git a/apps/files_external/l10n/es_AR.php b/apps/files_external/l10n/es_AR.php index a0bb3a8dfe..c380c6d0d9 100644 --- a/apps/files_external/l10n/es_AR.php +++ b/apps/files_external/l10n/es_AR.php @@ -1,27 +1,27 @@ "Ubicación", +"URL" => "URL", +"Username" => "Nombre de usuario", +"Password" => "Contraseña", +"Share" => "Compartir", "Access granted" => "Acceso permitido", "Error configuring Dropbox storage" => "Error al configurar el almacenamiento de Dropbox", "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.", +"Saved" => "Guardado", "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", "Delete" => "Borrar", "Enable User External Storage" => "Habilitar almacenamiento de usuario externo", -"Allow users to mount their own external storage" => "Permitir a los usuarios montar su propio almacenamiento externo", "SSL root certificates" => "certificados SSL raíz", "Import Root Certificate" => "Importar certificado raíz" ); diff --git a/apps/files_external/l10n/es_CL.php b/apps/files_external/l10n/es_CL.php new file mode 100644 index 0000000000..2bc6da9a59 --- /dev/null +++ b/apps/files_external/l10n/es_CL.php @@ -0,0 +1,8 @@ + "Usuario", +"Password" => "Clave", +"Share" => "Compartir", +"Folder name" => "Nombre del directorio" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/es_MX.php b/apps/files_external/l10n/es_MX.php index b508df8476..73ce835910 100644 --- a/apps/files_external/l10n/es_MX.php +++ b/apps/files_external/l10n/es_MX.php @@ -1,27 +1,26 @@ "Ubicación", +"URL" => "URL", +"Username" => "Nombre de usuario", +"Password" => "Contraseña", +"Share" => "Compartir", "Access granted" => "Acceso concedido", "Error configuring Dropbox storage" => "Error configurando el almacenamiento de Dropbox", "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", "Delete" => "Eliminar", "Enable User External Storage" => "Habilitar almacenamiento externo de usuario", -"Allow users to mount their own external storage" => "Permitir a los usuarios montar su propio almacenamiento externo", "SSL root certificates" => "Certificados raíz SSL", "Import Root Certificate" => "Importar certificado raíz" ); diff --git a/apps/files_external/l10n/et_EE.php b/apps/files_external/l10n/et_EE.php index a7e623eb7d..e5fc7c6937 100644 --- a/apps/files_external/l10n/et_EE.php +++ b/apps/files_external/l10n/et_EE.php @@ -1,27 +1,36 @@ "Kohalik", +"Location" => "Asukoht", +"URL" => "URL", +"Username" => "Kasutajanimi", +"Password" => "Parool", +"Share" => "Jaga", "Access granted" => "Ligipääs on antud", "Error configuring Dropbox storage" => "Viga Dropboxi salvestusruumi seadistamisel", "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", +"Note: " => "Märkus:", +" 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." => "Märkus: cURL tugi puudub PHP paigalduses. FTP %s hoidla ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata cURL tugi.", +"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." => "Märkus: FTP tugi puudub PHP paigalduses. FTP %s hoidla ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata FTP tugi.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Märkus: \"%s\" pole paigaldatud. Hoidla %s ühendamine pole võimalik. Palu oma süsteemihalduril paigaldata vajalik tugi.", "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 their own external storage" => "Luba kasutajatel ühendada külge nende enda välised salvestusseadmed", +"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 db92e2f001..28376b56b6 100644 --- a/apps/files_external/l10n/eu.php +++ b/apps/files_external/l10n/eu.php @@ -1,27 +1,35 @@ "Bertakoa", +"Location" => "Kokapena", +"Amazon S3" => "Amazon S3", +"Port (optional)" => "Portua (hautazkoa)", +"Enable SSL" => "Gaitu SSL", +"URL" => "URL", +"Username" => "Erabiltzaile izena", +"Password" => "Pasahitza", +"Share" => "Partekatu", "Access granted" => "Sarrera baimendua", "Error configuring Dropbox storage" => "Errore bat egon da Dropbox biltegiratzea konfiguratzean", "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. ", +"Saved" => "Gordeta", +"Note: " => "Oharra:", +" and " => "eta", "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", +"No user or group" => "Talde edo erabiltzailerik ez", "All Users" => "Erabiltzaile guztiak", "Groups" => "Taldeak", "Users" => "Erabiltzaileak", "Delete" => "Ezabatu", "Enable User External Storage" => "Gaitu erabiltzaileentzako Kanpo Biltegiratzea", -"Allow users to mount their own external storage" => "Baimendu erabiltzaileak bere kanpo biltegiratzeak muntatzen", +"Allow users to mount the following external storage" => "Baimendu erabiltzaileak hurrengo kanpo biltegiratzeak muntatzen", "SSL root certificates" => "SSL erro ziurtagiriak", "Import Root Certificate" => "Inportatu Erro Ziurtagiria" ); diff --git a/apps/files_external/l10n/eu_ES.php b/apps/files_external/l10n/eu_ES.php new file mode 100644 index 0000000000..9b95b9d01a --- /dev/null +++ b/apps/files_external/l10n/eu_ES.php @@ -0,0 +1,6 @@ + "kokapena", +"Delete" => "Ezabatu" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/fa.php b/apps/files_external/l10n/fa.php index 216893811c..6bf8ce8af5 100644 --- a/apps/files_external/l10n/fa.php +++ b/apps/files_external/l10n/fa.php @@ -1,27 +1,26 @@ "محل", +"URL" => "آدرس", +"Username" => "نام کاربری", +"Password" => "گذرواژه", +"Share" => "اشتراک‌گذاری", "Access granted" => "مجوز دسترسی صادر شد", "Error configuring Dropbox storage" => "خطا به هنگام تنظیم فضای دراپ باکس", "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" => "کاربران", "Delete" => "حذف", "Enable User External Storage" => "فعال سازی حافظه خارجی کاربر", -"Allow users to mount their own external storage" => "اجازه به کاربران برای متصل کردن منابع ذخیره ی خارجی خودشان", "SSL root certificates" => "گواهی های اصلی SSL ", "Import Root Certificate" => "وارد کردن گواهی اصلی" ); diff --git a/apps/files_external/l10n/fi_FI.php b/apps/files_external/l10n/fi_FI.php index 9632aa255e..9efc8e09cb 100644 --- a/apps/files_external/l10n/fi_FI.php +++ b/apps/files_external/l10n/fi_FI.php @@ -1,27 +1,41 @@ "Paikallinen", +"Location" => "Sijainti", +"Amazon S3" => "Amazon S3", +"Port (optional)" => "Portti (valinnainen)", +"Region (optional)" => "Alue (valinnainen)", +"Enable SSL" => "Käytä SSL:ää", +"URL" => "Verkko-osoite", +"Username" => "Käyttäjätunnus", +"Password" => "Salasana", +"Username (required)" => "Käyttäjätunnus (vaaditaan)", +"Share" => "Jaa", "Access granted" => "Pääsy sallittu", "Error configuring Dropbox storage" => "Virhe Dropbox levyn asetuksia tehtäessä", "Grant access" => "Salli pääsy", "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ä", -"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.", +"Saved" => "Tallennettu", +"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", "Delete" => "Poista", "Enable User External Storage" => "Ota käyttöön ulkopuoliset tallennuspaikat", -"Allow users to mount their own external storage" => "Salli käyttäjien liittää omia erillisiä tallennusvälineitä", +"Allow users to mount the following external storage" => "Salli käyttäjien liittää seuraavat erilliset tallennusvälineet", "SSL root certificates" => "SSL-juurivarmenteet", "Import Root Certificate" => "Tuo juurivarmenne" ); diff --git a/apps/files_external/l10n/fr.php b/apps/files_external/l10n/fr.php index f6b1a75200..c03a2f49e0 100644 --- a/apps/files_external/l10n/fr.php +++ b/apps/files_external/l10n/fr.php @@ -1,27 +1,39 @@ "Local", +"Location" => "Emplacement", +"Amazon S3" => "Amazon S3", +"Key" => "Clé", +"Access Key" => "Clé d'accès", +"URL" => "URL", +"Username" => "Nom d'utilisateur", +"Password" => "Mot de passe", +"Share" => "Partager", "Access granted" => "Accès autorisé", "Error configuring Dropbox storage" => "Erreur lors de la configuration du support de stockage Dropbox", "Grant access" => "Autoriser l'accès", "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", -"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.", +"Saved" => "Sauvegarder", +"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", "Delete" => "Supprimer", "Enable User External Storage" => "Activer le stockage externe pour les utilisateurs", -"Allow users to mount their own external storage" => "Autoriser les utilisateurs à monter leur propre stockage externe", +"Allow users to mount the following external storage" => "Autorise les utilisateurs à monter les stockage externes suivants", "SSL root certificates" => "Certificats racine SSL", "Import Root Certificate" => "Importer un certificat racine" ); diff --git a/apps/files_external/l10n/gl.php b/apps/files_external/l10n/gl.php index 3dda999dd1..ccbdcce7f3 100644 --- a/apps/files_external/l10n/gl.php +++ b/apps/files_external/l10n/gl.php @@ -1,27 +1,68 @@ "Local", +"Location" => "Localización", +"Amazon S3" => "Amazon S3", +"Key" => "Clave", +"Secret" => "Secreto", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 e compatíbeis", +"Access Key" => "Clave de acceso", +"Secret Key" => "Clave secreta", +"Hostname (optional)" => "Nome de máquina (opcional)", +"Port (optional)" => "Porto (opcional)", +"Region (optional)" => "Rexión (opcional)", +"Enable SSL" => "Activar SSL", +"Enable Path Style" => "Activar o estilo de ruta", +"App key" => "Clave da API", +"App secret" => "Secreto do aplicativo", +"URL" => "URL", +"Username" => "Nome de usuario", +"Password" => "Contrasinal", +"Root" => "Root (raíz)", +"Secure ftps://" => "ftps:// seguro", +"Client ID" => "ID do cliente", +"Client secret" => "Secreto do cliente", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "Nome de usuario (obrigatorio)", +"Bucket (required)" => "Bucket (obrigatorio)", +"Region (optional for OpenStack Object Storage)" => "Rexión (opcional para OpenStack Object Storage)", +"API Key (required for Rackspace Cloud Files)" => "Clave da API (obrigatoria para Rackspace Cloud Files)", +"Tenantname (required for OpenStack Object Storage)" => "Nome do inquilino (obrigatorio para OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Contrasinal (obrigatorio para OpenStack Object Storage)", +"Service Name (required for OpenStack Object Storage)" => "Nome do servizo (obrigatorio para OpenStack Object Storage)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL do punto final da identidade (obrigatorio para OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Tempo de espera de peticións HTTP en segundos (opcional)", +"Share" => "Compartir", +"SMB / CIFS using OC login" => "SMB / CIFS usando acceso OC", +"Username as share" => "Nome de usuario como compartición", +"Secure https://" => "https:// seguro", +"Remote subfolder" => "Subcartafol remoto", "Access granted" => "Concedeuse acceso", "Error configuring Dropbox storage" => "Produciuse un erro ao configurar o almacenamento en Dropbox", "Grant access" => "Permitir o acceso", "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", -"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.", +"Saved" => "Gardado", +"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", "Delete" => "Eliminar", "Enable User External Storage" => "Activar o almacenamento externo do usuario", -"Allow users to mount their own external storage" => "Permitir aos usuarios montar os seus propios almacenamentos externos", +"Allow users to mount the following external storage" => "Permitirlle aos usuarios montar o seguinte almacenamento externo", "SSL root certificates" => "Certificados SSL root", "Import Root Certificate" => "Importar o certificado root" ); diff --git a/apps/files_external/l10n/he.php b/apps/files_external/l10n/he.php index e99c9f5193..67cbb0cba2 100644 --- a/apps/files_external/l10n/he.php +++ b/apps/files_external/l10n/he.php @@ -1,5 +1,10 @@ "מיקום", +"URL" => "כתובת", +"Username" => "שם משתמש", +"Password" => "סיסמא", +"Share" => "שיתוף", "Access granted" => "הוענקה גישה", "Error configuring Dropbox storage" => "אירעה שגיאה בעת הגדרת אחסון ב־Dropbox", "Grant access" => "הענקת גישה", @@ -9,14 +14,11 @@ $TRANSLATIONS = array( "Folder name" => "שם התיקייה", "Configuration" => "הגדרות", "Options" => "אפשרויות", -"Applicable" => "ניתן ליישום", -"None set" => "לא הוגדרה", "All Users" => "כל המשתמשים", "Groups" => "קבוצות", "Users" => "משתמשים", "Delete" => "מחיקה", "Enable User External Storage" => "הפעלת אחסון חיצוני למשתמשים", -"Allow users to mount their own external storage" => "יאפשר למשתמשים לעגן את האחסון החיצוני שלהם", "SSL root certificates" => "שורש אישורי אבטחת SSL ", "Import Root Certificate" => "ייבוא אישור אבטחת שורש" ); diff --git a/apps/files_external/l10n/hi.php b/apps/files_external/l10n/hi.php index 7df9657259..fdea5e7625 100644 --- a/apps/files_external/l10n/hi.php +++ b/apps/files_external/l10n/hi.php @@ -1,5 +1,8 @@ "प्रयोक्ता का नाम", +"Password" => "पासवर्ड", +"Share" => "साझा करें", "Users" => "उपयोगकर्ता" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/hr.php b/apps/files_external/l10n/hr.php index 91536e0b87..954a484b79 100644 --- a/apps/files_external/l10n/hr.php +++ b/apps/files_external/l10n/hr.php @@ -1,5 +1,9 @@ "Lokacija", +"Username" => "Korisničko ime", +"Password" => "Lozinka", +"Share" => "Podijeli", "Groups" => "Grupe", "Users" => "Korisnici", "Delete" => "Obriši" diff --git a/apps/files_external/l10n/hu_HU.php b/apps/files_external/l10n/hu_HU.php index 23fe916eba..831bd69c23 100644 --- a/apps/files_external/l10n/hu_HU.php +++ b/apps/files_external/l10n/hu_HU.php @@ -1,27 +1,27 @@ "Hely", +"URL" => "URL", +"Username" => "Felhasználónév", +"Password" => "Jelszó", +"Share" => "Megosztás", "Access granted" => "Érvényes hozzáférés", "Error configuring Dropbox storage" => "A Dropbox tárolót nem sikerült beállítani", "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!", +"Saved" => "Elmentve", "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", "Delete" => "Törlés", "Enable User External Storage" => "Külső tárolók engedélyezése a felhasználók részére", -"Allow users to mount their own external storage" => "Lehetővé teszi, hogy a felhasználók külső tárolási szolgáltatásokat csatoljanak be a saját területükre", "SSL root certificates" => "SSL tanúsítványok", "Import Root Certificate" => "SSL tanúsítványok importálása" ); diff --git a/apps/files_external/l10n/ia.php b/apps/files_external/l10n/ia.php index 47b0f89b8b..844af213d8 100644 --- a/apps/files_external/l10n/ia.php +++ b/apps/files_external/l10n/ia.php @@ -1,5 +1,11 @@ "Loco", +"URL" => "URL", +"Username" => "Nomine de usator", +"Password" => "Contrasigno", +"Share" => "Compartir", +"Folder name" => "Nomine de dossier", "Groups" => "Gruppos", "Users" => "Usatores", "Delete" => "Deler" diff --git a/apps/files_external/l10n/id.php b/apps/files_external/l10n/id.php index 53ab79ae7e..dd383c4636 100644 --- a/apps/files_external/l10n/id.php +++ b/apps/files_external/l10n/id.php @@ -1,26 +1,43 @@ "Lokal", +"Location" => "lokasi", +"Amazon S3" => "Amazon S3", +"Hostname (optional)" => "Hostname (tambahan)", +"Port (optional)" => "Port (tambahan)", +"Region (optional)" => "Wilayah (tambahan)", +"Enable SSL" => "Aktifkan SSL", +"URL" => "tautan", +"Username" => "Nama Pengguna", +"Password" => "Sandi", +"Root" => "Root", +"Username (required)" => "Nama pengguna (dibutuhkan)", +"Share" => "Bagikan", "Access granted" => "Akses diberikan", "Error configuring Dropbox storage" => "Kesalahan dalam mengonfigurasi penyimpanan Dropbox", "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.", +"Saved" => "Disimpan", +"Note: " => "Catatan: ", +" and " => "dan", +"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." => "Catatan: Dukungan cURL di PHP tidak diaktifkan atau belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan tanyakan ke administrator sistem Anda untuk menginstalnya.", +"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." => "Catatan: Dukungan FTP di PHP tidak diaktifkan atau belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan tanyakan ke administrator sistem Anda untuk menginstalnya.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Catatan: \"%s\" belum diinstal. Mengaitkan %s tidak dimungkinkan. Silakan tanyakan ke administrator sistem Anda untuk menginstalnya.", "External Storage" => "Penyimpanan Eksternal", "Folder name" => "Nama folder", "External storage" => "Penyimpanan eksternal", "Configuration" => "Konfigurasi", "Options" => "Opsi", -"Applicable" => "Berlaku", +"Available for" => "Tersedia untuk", "Add storage" => "Tambahkan penyimpanan", -"None set" => "Tidak satupun di set", +"No user or group" => "Tidak ada pengguna dan grup", "All Users" => "Semua Pengguna", "Groups" => "Grup", "Users" => "Pengguna", "Delete" => "Hapus", "Enable User External Storage" => "Aktifkan Penyimpanan Eksternal Pengguna", -"Allow users to mount their own external storage" => "Izinkan pengguna untuk mengaitkan penyimpanan eksternal mereka", +"Allow users to mount the following external storage" => "Izinkan pengguna untuk mengaitkan penyimpanan eksternal berikut", "SSL root certificates" => "Sertifikat root SSL", "Import Root Certificate" => "Impor Sertifikat Root" ); diff --git a/apps/files_external/l10n/is.php b/apps/files_external/l10n/is.php index d2229d1fcd..39b750189d 100644 --- a/apps/files_external/l10n/is.php +++ b/apps/files_external/l10n/is.php @@ -1,24 +1,24 @@ "Staðsetning", +"URL" => "URL", +"Username" => "Notendanafn", +"Password" => "Lykilorð", +"Share" => "Deila", "Access granted" => "Aðgengi veitt", "Error configuring Dropbox storage" => "Villa við að setja upp Dropbox gagnasvæði", "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", "Delete" => "Eyða", "Enable User External Storage" => "Virkja ytra gagnasvæði notenda", -"Allow users to mount their own external storage" => "Leyfa notendum að bæta við sínum eigin ytri gagnasvæðum", "SSL root certificates" => "SSL rótar skilríki", "Import Root Certificate" => "Flytja inn rótar skilríki" ); diff --git a/apps/files_external/l10n/it.php b/apps/files_external/l10n/it.php index b53663beb5..bc5b9d6dce 100644 --- a/apps/files_external/l10n/it.php +++ b/apps/files_external/l10n/it.php @@ -1,27 +1,68 @@ "Locale", +"Location" => "Posizione", +"Amazon S3" => "Amazon S3", +"Key" => "Chiave", +"Secret" => "Segreto", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 e conformi", +"Access Key" => "Chiave di accesso", +"Secret Key" => "Chiave segreta", +"Hostname (optional)" => "Nome host (opzionale)", +"Port (optional)" => "Porta (opzionale)", +"Region (optional)" => "Regione (opzionale)", +"Enable SSL" => "Abilita SSL", +"Enable Path Style" => "Abilita stile percorsi", +"App key" => "Chiave applicazione", +"App secret" => "Segreto applicazione", +"URL" => "URL", +"Username" => "Nome utente", +"Password" => "Password", +"Root" => "Radice", +"Secure ftps://" => "Sicuro ftps://", +"Client ID" => "ID client", +"Client secret" => "Segreto del client", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "Nome utente (richiesto)", +"Bucket (required)" => "Bucket (richiesto)", +"Region (optional for OpenStack Object Storage)" => "Regione (facoltativa per OpenStack Object Storage)", +"API Key (required for Rackspace Cloud Files)" => "Chiave API (richiesta per Rackspace Cloud Files)", +"Tenantname (required for OpenStack Object Storage)" => "Nome tenant (richiesto per OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Password (richiesta per OpenStack Object Storage)", +"Service Name (required for OpenStack Object Storage)" => "Nome servizio (richiesta per OpenStack Object Storage)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL del servizio di identità (richiesto per OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Tempo massimo in secondi delle richieste HTTP (opzionale)", +"Share" => "Condividi", +"SMB / CIFS using OC login" => "SMB / CIFS utilizzando le credenziali di OC", +"Username as share" => "Nome utente come condivisione", +"Secure https://" => "Sicuro https://", +"Remote subfolder" => "Sottocartella remota", "Access granted" => "Accesso consentito", "Error configuring Dropbox storage" => "Errore durante la configurazione dell'archivio Dropbox", "Grant access" => "Concedi l'accesso", "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", -"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.", +"Saved" => "Salvato", +"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", "Delete" => "Elimina", "Enable User External Storage" => "Abilita la memoria esterna dell'utente", -"Allow users to mount their own external storage" => "Consenti agli utenti di montare la propria memoria esterna", +"Allow users to mount the following external storage" => "Consenti agli utenti di montare la seguente memoria esterna", "SSL root certificates" => "Certificati SSL radice", "Import Root Certificate" => "Importa certificato radice" ); diff --git a/apps/files_external/l10n/ja.php b/apps/files_external/l10n/ja.php new file mode 100644 index 0000000000..4ac746caa0 --- /dev/null +++ b/apps/files_external/l10n/ja.php @@ -0,0 +1,31 @@ + "ローカル", +"Location" => "位置", +"URL" => "URL", +"Username" => "ユーザー名", +"Password" => "パスワード", +"Share" => "共有", +"Access granted" => "アクセスは許可されました", +"Error configuring Dropbox storage" => "Dropboxストレージの設定エラー", +"Grant access" => "アクセスを許可", +"Please provide a valid Dropbox app key and secret." => "有効なDropboxアプリのキーとパスワードを入力してください。", +"Error configuring Google Drive storage" => "Googleドライブストレージの設定エラー", +"Saved" => "保存されました", +"External Storage" => "外部ストレージ", +"Folder name" => "フォルダー名", +"External storage" => "外部ストレージ", +"Configuration" => "設定", +"Options" => "オプション", +"Add storage" => "ストレージを追加", +"No user or group" => "ユーザーもしくはグループがありません", +"All Users" => "すべてのユーザー", +"Groups" => "グループ", +"Users" => "ユーザー", +"Delete" => "削除", +"Enable User External Storage" => "ユーザーの外部ストレージを有効にする", +"Allow users to mount the following external storage" => "ユーザに以下の外部ストレージのマウントを許可する", +"SSL root certificates" => "SSLルート証明書", +"Import Root Certificate" => "ルート証明書をインポート" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_external/l10n/ja_JP.php b/apps/files_external/l10n/ja_JP.php index fc528f035c..312dc85188 100644 --- a/apps/files_external/l10n/ja_JP.php +++ b/apps/files_external/l10n/ja_JP.php @@ -3,25 +3,26 @@ $TRANSLATIONS = array( "Access granted" => "アクセスは許可されました", "Error configuring Dropbox storage" => "Dropboxストレージの設定エラー", "Grant access" => "アクセスを許可", -"Please provide a valid Dropbox app key and secret." => "有効なDropboxアプリのキーとパスワードを入力して下さい。", +"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 もしくは GoogleDrive のマウントはできません。システム管理者にインストールをお願いして下さい。", +"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" => "フォルダ名", +"Folder name" => "フォルダー名", "External storage" => "外部ストレージ", "Configuration" => "設定", "Options" => "オプション", "Applicable" => "適用範囲", "Add storage" => "ストレージを追加", "None set" => "未設定", -"All Users" => "すべてのユーザ", +"All Users" => "すべてのユーザー", "Groups" => "グループ", -"Users" => "ユーザ", +"Users" => "ユーザー", "Delete" => "削除", -"Enable User External Storage" => "ユーザの外部ストレージを有効にする", -"Allow users to mount their own external storage" => "ユーザに外部ストレージのマウントを許可する", +"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/jv.php b/apps/files_external/l10n/jv.php new file mode 100644 index 0000000000..acff46664c --- /dev/null +++ b/apps/files_external/l10n/jv.php @@ -0,0 +1,5 @@ + "Papan panggonan" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/ka_GE.php b/apps/files_external/l10n/ka_GE.php index 445d40e708..f7eb01ba94 100644 --- a/apps/files_external/l10n/ka_GE.php +++ b/apps/files_external/l10n/ka_GE.php @@ -1,27 +1,26 @@ "ადგილმდებარეობა", +"URL" => "URL", +"Username" => "მომხმარებლის სახელი", +"Password" => "პაროლი", +"Share" => "გაზიარება", "Access granted" => "დაშვება მინიჭებულია", "Error configuring Dropbox storage" => "შეცდომა Dropbox საცავის კონფიგურირების დროს", "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" => "მომხმარებელი", "Delete" => "წაშლა", "Enable User External Storage" => "მომხმარებლის ექსტერნალ საცავის აქტივირება", -"Allow users to mount their own external storage" => "მიეცით მომხმარებლებს თავისი ექსტერნალ საცავის მონტირების უფლება", "SSL root certificates" => "SSL root სერთიფიკატები", "Import Root Certificate" => "Root სერთიფიკატის იმპორტირება" ); diff --git a/apps/files_external/l10n/km.php b/apps/files_external/l10n/km.php index f7d9faa38c..aac6337024 100644 --- a/apps/files_external/l10n/km.php +++ b/apps/files_external/l10n/km.php @@ -1,5 +1,14 @@ "ទីតាំង", +"URL" => "URL", +"Username" => "ឈ្មោះ​អ្នកប្រើ", +"Password" => "ពាក្យសម្ងាត់", +"Share" => "ចែក​រំលែក", +"Folder name" => "ឈ្មោះ​ថត", +"Options" => "ជម្រើស", +"Groups" => "ក្រុ", +"Users" => "អ្នកប្រើ", "Delete" => "លុប" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_external/l10n/ko.php b/apps/files_external/l10n/ko.php index 64d815a5bc..6ae8ffdeb8 100644 --- a/apps/files_external/l10n/ko.php +++ b/apps/files_external/l10n/ko.php @@ -1,27 +1,28 @@ "장소", +"Amazon S3" => "Amazon S3", +"URL" => "URL", +"Username" => "사용자 이름", +"Password" => "암호", +"Share" => "공유", "Access granted" => "접근 허가됨", "Error configuring Dropbox storage" => "Dropbox 저장소 설정 오류", "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 드라이브 공유를 마운트할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", +"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 their own external storage" => "사용자별 외부 저장소 마운트 허용", "SSL root certificates" => "SSL 루트 인증서", "Import Root Certificate" => "루트 인증서 가져오기" ); diff --git a/apps/files_external/l10n/ku_IQ.php b/apps/files_external/l10n/ku_IQ.php index 39778bce07..72cc813352 100644 --- a/apps/files_external/l10n/ku_IQ.php +++ b/apps/files_external/l10n/ku_IQ.php @@ -1,5 +1,10 @@ "شوێن", +"URL" => "ناونیشانی به‌سته‌ر", +"Username" => "ناوی به‌کارهێنه‌ر", +"Password" => "وشەی تێپەربو", +"Share" => "هاوبەشی کردن", "Folder name" => "ناوی بوخچه", "Users" => "به‌كارهێنه‌ر" ); diff --git a/apps/files_external/l10n/lb.php b/apps/files_external/l10n/lb.php index 13233bf362..49517e7af3 100644 --- a/apps/files_external/l10n/lb.php +++ b/apps/files_external/l10n/lb.php @@ -1,5 +1,10 @@ "Uert", +"URL" => "URL", +"Username" => "Benotzernumm", +"Password" => "Passwuert", +"Share" => "Deelen", "Folder name" => "Dossiers Numm:", "Groups" => "Gruppen", "Users" => "Benotzer", diff --git a/apps/files_external/l10n/lt_LT.php b/apps/files_external/l10n/lt_LT.php index 57cdfe6722..736becc58d 100644 --- a/apps/files_external/l10n/lt_LT.php +++ b/apps/files_external/l10n/lt_LT.php @@ -1,27 +1,26 @@ "Vieta", +"URL" => "URL", +"Username" => "Prisijungimo vardas", +"Password" => "Slaptažodis", +"Share" => "Dalintis", "Access granted" => "Priėjimas suteiktas", "Error configuring Dropbox storage" => "Klaida nustatinėjant Dropbox talpyklą", "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", "Delete" => "Ištrinti", "Enable User External Storage" => "Įjungti vartotojų išorines saugyklas", -"Allow users to mount their own external storage" => "Leisti vartotojams pridėti savo išorines saugyklas", "SSL root certificates" => "SSL sertifikatas", "Import Root Certificate" => "Įkelti pagrindinį sertifikatą" ); diff --git a/apps/files_external/l10n/lv.php b/apps/files_external/l10n/lv.php index d0db01a22b..3506e55323 100644 --- a/apps/files_external/l10n/lv.php +++ b/apps/files_external/l10n/lv.php @@ -1,27 +1,26 @@ "Vieta", +"URL" => "URL", +"Username" => "Lietotājvārds", +"Password" => "Parole", +"Share" => "Dalīties", "Access granted" => "Piešķirta pieeja", "Error configuring Dropbox storage" => "Kļūda, konfigurējot Dropbox krātuvi", "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", "Delete" => "Dzēst", "Enable User External Storage" => "Aktivēt lietotāja ārējo krātuvi", -"Allow users to mount their own external storage" => "Ļaut lietotājiem montēt pašiem savu ārējo krātuvi", "SSL root certificates" => "SSL saknes sertifikāti", "Import Root Certificate" => "Importēt saknes sertifikātus" ); diff --git a/apps/files_external/l10n/mk.php b/apps/files_external/l10n/mk.php index e410b398ac..0a72b65168 100644 --- a/apps/files_external/l10n/mk.php +++ b/apps/files_external/l10n/mk.php @@ -1,24 +1,24 @@ "Локација", +"URL" => "Адреса", +"Username" => "Корисничко име", +"Password" => "Лозинка", +"Share" => "Сподели", "Access granted" => "Пристапот е дозволен", "Error configuring Dropbox storage" => "Грешка при конфигурација на Dropbox", "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" => "Корисници", "Delete" => "Избриши", "Enable User External Storage" => "Овозможи надворешни за корисници", -"Allow users to mount their own external storage" => "Дозволи им на корисниците да монтираат свои надворешни дискови", "SSL root certificates" => "SSL root сертификати", "Import Root Certificate" => "Увези" ); diff --git a/apps/files_external/l10n/ms_MY.php b/apps/files_external/l10n/ms_MY.php index 4e33263a86..789527e4a4 100644 --- a/apps/files_external/l10n/ms_MY.php +++ b/apps/files_external/l10n/ms_MY.php @@ -1,5 +1,10 @@ "Lokasi", +"URL" => "URL", +"Username" => "Nama pengguna", +"Password" => "Kata laluan", +"Share" => "Kongsi", "Groups" => "Kumpulan", "Users" => "Pengguna", "Delete" => "Padam" diff --git a/apps/files_external/l10n/my_MM.php b/apps/files_external/l10n/my_MM.php index 1cbe5f0fe5..775fa4d988 100644 --- a/apps/files_external/l10n/my_MM.php +++ b/apps/files_external/l10n/my_MM.php @@ -1,5 +1,8 @@ "တည်နေရာ", +"Username" => "သုံးစွဲသူအမည်", +"Password" => "စကားဝှက်", "Users" => "သုံးစွဲသူ" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_external/l10n/nb_NO.php b/apps/files_external/l10n/nb_NO.php index cb31ac8922..f1f0a09fd5 100644 --- a/apps/files_external/l10n/nb_NO.php +++ b/apps/files_external/l10n/nb_NO.php @@ -1,27 +1,36 @@ "Lokal", +"Location" => "Sted", +"Amazon S3" => "Amazon S3", +"URL" => "URL", +"Username" => "Brukernavn", +"Password" => "Passord", +"Share" => "Del", "Access granted" => "Tilgang innvilget", "Error configuring Dropbox storage" => "Feil ved konfigurering av Dropbox-lagring", "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", +"Note: " => "Notat: ", +" and " => "og", +"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." => "Merk: Støtte for cURL i PHP er ikke aktivert eller installert. Montering av %s er ikke mulig. Be systemadministratoren om å installere 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." => "Merk: FTP støtte i PHP er ikke slått på eller innstallert. Kan ikke montere %s. Ta kontakt med din systemadministrator for å installere det.", "External Storage" => "Ekstern lagring", "Folder name" => "Mappenavn", "External storage" => "Ekstern lagringsplass", "Configuration" => "Konfigurasjon", "Options" => "Innstillinger", -"Applicable" => "Anvendelig", +"Available for" => "Tilgjengelig for", "Add storage" => "Legg til lagringsplass", -"None set" => "Ingen valgt", +"No user or group" => "Ingen bruker eller gruppe", "All Users" => "Alle brukere", "Groups" => "Grupper", "Users" => "Brukere", "Delete" => "Slett", "Enable User External Storage" => "Aktiver ekstern lagring for bruker", -"Allow users to mount their own external storage" => "Tillat brukere å koble til egne eksterne lagringsmedium", +"Allow users to mount the following external storage" => "Tillat brukere å montere følgende eksterne lagring", "SSL root certificates" => "SSL root-sertifikater", "Import Root Certificate" => "Importer root-sertifikat" ); diff --git a/apps/files_external/l10n/nl.php b/apps/files_external/l10n/nl.php index 35e63b09a3..2e88c18740 100644 --- a/apps/files_external/l10n/nl.php +++ b/apps/files_external/l10n/nl.php @@ -1,27 +1,68 @@ "Lokaal", +"Location" => "Locatie", +"Amazon S3" => "Amazon S3", +"Key" => "Sleutel", +"Secret" => "Geheim", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 en overeenkomstig", +"Access Key" => "Access Key", +"Secret Key" => "Secret Key", +"Hostname (optional)" => "Hostname (optioneel)", +"Port (optional)" => "Poort (optioneel)", +"Region (optional)" => "Regio (optioneel)", +"Enable SSL" => "Activeren SSL", +"Enable Path Style" => "Activeren pad stijl", +"App key" => "App key", +"App secret" => "App secret", +"URL" => "URL", +"Username" => "Gebruikersnaam", +"Password" => "Wachtwoord", +"Root" => "Root", +"Secure ftps://" => "Secure ftps://", +"Client ID" => "Client ID", +"Client secret" => "Client secret", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "Gebruikersnaam (verplicht)", +"Bucket (required)" => "Bucket (verplicht)", +"Region (optional for OpenStack Object Storage)" => "Regio (optioneel voor OpenStack Object Storage)", +"API Key (required for Rackspace Cloud Files)" => "API Key (verplicht voor Rackspace Cloud Files)", +"Tenantname (required for OpenStack Object Storage)" => "Tenantname (Verplicht voor OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Wachtwoord (verplicht voor OpenStack Object Storage)", +"Service Name (required for OpenStack Object Storage)" => "Service Name (verplicht voor OpenStack Object Storage)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL van identity endpoint (verplicht voor OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Time-out van HTTP aanvragen in seconden (optioneel)", +"Share" => "Share", +"SMB / CIFS using OC login" => "SMB / CIFS via OC inlog", +"Username as share" => "Gebruikersnaam als share", +"Secure https://" => "Secure https://", +"Remote subfolder" => "Externe submap", "Access granted" => "Toegang toegestaan", "Error configuring Dropbox storage" => "Fout tijdens het configureren van Dropbox opslag", "Grant access" => "Sta toegang toe", "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", -"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.", +"Saved" => "Bewaard", +"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", "Delete" => "Verwijder", "Enable User External Storage" => "Externe opslag voor gebruikers activeren", -"Allow users to mount their own external storage" => "Sta gebruikers toe om hun eigen externe opslag aan te koppelen", +"Allow users to mount the following external storage" => "Sta gebruikers toe de volgende externe opslag aan te koppelen", "SSL root certificates" => "SSL root certificaten", "Import Root Certificate" => "Importeer root certificaat" ); diff --git a/apps/files_external/l10n/nn_NO.php b/apps/files_external/l10n/nn_NO.php index 7bb38f14ce..542d3ec042 100644 --- a/apps/files_external/l10n/nn_NO.php +++ b/apps/files_external/l10n/nn_NO.php @@ -1,5 +1,11 @@ "Stad", +"URL" => "Nettstad", +"Username" => "Brukarnamn", +"Password" => "Passord", +"Share" => "Del", +"Folder name" => "Mappenamn", "Configuration" => "Innstillingar", "Groups" => "Grupper", "Users" => "Brukarar", diff --git a/apps/files_external/l10n/oc.php b/apps/files_external/l10n/oc.php index 99f2fd507d..e854c9f25a 100644 --- a/apps/files_external/l10n/oc.php +++ b/apps/files_external/l10n/oc.php @@ -1,5 +1,10 @@ "Plaça", +"URL" => "URL", +"Username" => "Non d'usancièr", +"Password" => "Senhal", +"Share" => "Parteja", "Groups" => "Grops", "Users" => "Usancièrs", "Delete" => "Escafa" diff --git a/apps/files_external/l10n/pa.php b/apps/files_external/l10n/pa.php index d633784f5c..0bdcf0b7f6 100644 --- a/apps/files_external/l10n/pa.php +++ b/apps/files_external/l10n/pa.php @@ -1,5 +1,8 @@ "ਯੂਜ਼ਰ-ਨਾਂ", +"Password" => "ਪਾਸਵਰ", +"Share" => "ਸਾਂਝਾ ਕਰੋ", "Groups" => "ਗਰੁੱਪ", "Delete" => "ਹਟਾਓ" ); diff --git a/apps/files_external/l10n/pl.php b/apps/files_external/l10n/pl.php index f5501b9755..9c13371b16 100644 --- a/apps/files_external/l10n/pl.php +++ b/apps/files_external/l10n/pl.php @@ -1,27 +1,68 @@ "Lokalny", +"Location" => "Lokalizacja", +"Amazon S3" => "Amazon S3", +"Key" => "Klucz", +"Secret" => "Hasło", +"Bucket" => "Kosz", +"Amazon S3 and compliant" => "Amazon S3 i zgodne", +"Access Key" => "Klucz dostępu", +"Secret Key" => "Klucz hasła", +"Hostname (optional)" => "Nazwa hosta (opcjonalnie)", +"Port (optional)" => "Port (opcjonalnie)", +"Region (optional)" => "Region (opcjonalnie)", +"Enable SSL" => "Włącz SSL", +"Enable Path Style" => "Włącz styl ścieżki", +"App key" => "Klucz aplikacji", +"App secret" => "Hasło aplikacji", +"URL" => "URL", +"Username" => "Nazwa użytkownika", +"Password" => "Hasło", +"Root" => "Root", +"Secure ftps://" => "Bezpieczny ftps://", +"Client ID" => "ID klienta", +"Client secret" => "Hasło klienta", +"OpenStack Object Storage" => "Magazyn obiektów OpenStack", +"Username (required)" => "Użytkownik (wymagany)", +"Bucket (required)" => "Kosz (wymagany)", +"Region (optional for OpenStack Object Storage)" => "Region (opcjonalny dla magazynu obiektów OpenStack)", +"API Key (required for Rackspace Cloud Files)" => "Klucz API (wymagany dla plików Rackspace Cloud)", +"Tenantname (required for OpenStack Object Storage)" => "Nazwa najemcy (wymagana dla magazynu obiektów OpenStack)", +"Password (required for OpenStack Object Storage)" => "Hasło (wymagane dla magazynu obiektów OpenStack)", +"Service Name (required for OpenStack Object Storage)" => "Nazwa usługi (wymagana dla magazynu obiektów OpenStack)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL lub zakończenie jednostki (wymagane dla magazynu obiektów OpenStack)", +"Timeout of HTTP requests in seconds (optional)" => "Czas wygaśnięcia żądań HTTP w sekundach (opcjonalne)", +"Share" => "Udostępnij", +"SMB / CIFS using OC login" => "SMB / CIFS przy użyciu loginu OC", +"Username as share" => "Użytkownik jako zasób", +"Secure https://" => "Bezpieczny https://", +"Remote subfolder" => "Zdalny podfolder", "Access granted" => "Dostęp do", "Error configuring Dropbox storage" => "Wystąpił błąd podczas konfigurowania zasobu Dropbox", "Grant access" => "Udziel dostępu", "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", -"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.", +"Saved" => "Zapisano", +"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", "Delete" => "Usuń", "Enable User External Storage" => "Włącz zewnętrzne zasoby dyskowe użytkownika", -"Allow users to mount their own external storage" => "Zezwalaj użytkownikom na montowanie ich własnych zewnętrznych zasobów dyskowych", +"Allow users to mount the following external storage" => "Pozwól użytkownikom montować następujące zewnętrzne zasoby dyskowe", "SSL root certificates" => "Główny certyfikat SSL", "Import Root Certificate" => "Importuj główny certyfikat" ); diff --git a/apps/files_external/l10n/pt_BR.php b/apps/files_external/l10n/pt_BR.php index f69bbc1ebe..d9544ae159 100644 --- a/apps/files_external/l10n/pt_BR.php +++ b/apps/files_external/l10n/pt_BR.php @@ -1,27 +1,68 @@ "Local", +"Location" => "Local", +"Amazon S3" => "Amazon S3", +"Key" => "Chave", +"Secret" => "Secreta", +"Bucket" => "Cesta", +"Amazon S3 and compliant" => "Amazon S3 e compatível", +"Access Key" => "Chave de Acesso", +"Secret Key" => "Chave Secreta", +"Hostname (optional)" => "Nome do Host (opcional)", +"Port (optional)" => "Porta (opcional)", +"Region (optional)" => "Região (opcional)", +"Enable SSL" => "Habilitar SSL", +"Enable Path Style" => "Habilitar Estilo do Caminho", +"App key" => "Chave do Aplicativo", +"App secret" => "Segredo da Aplicação", +"URL" => "URL", +"Username" => "Nome de Usuário", +"Password" => "Senha", +"Root" => "Raiz", +"Secure ftps://" => "Seguro ftps://", +"Client ID" => "ID do Cliente", +"Client secret" => "Segredo do cliente", +"OpenStack Object Storage" => "Armazenamento de Objetos OpenStack", +"Username (required)" => "Nome do Usuário (requerido)", +"Bucket (required)" => "Cesta (requerido)", +"Region (optional for OpenStack Object Storage)" => "Região (opcional para armazenamento de objetos OpenStack)", +"API Key (required for Rackspace Cloud Files)" => "Chave API (necessário para Rackspace Cloud File)", +"Tenantname (required for OpenStack Object Storage)" => "Nome Tenant (necessário para armazenamento de objetos OpenStack)", +"Password (required for OpenStack Object Storage)" => "Senha (necessário para armazenamento de objetos OpenStack)", +"Service Name (required for OpenStack Object Storage)" => "Nome do Serviço (necessário para armazenamento de objetos OpenStack)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "Ponto final de identidade da URL (obrigatório para armazenamento de objetos OpenStack)", +"Timeout of HTTP requests in seconds (optional)" => "Tempo limite de solicitações HTTP em segundos (opcional)", +"Share" => "Compartilhar", +"SMB / CIFS using OC login" => "SMB / CIFS usando OC logon", +"Username as share" => "Nome de usuário como compartilhado", +"Secure https://" => "https:// segura", +"Remote subfolder" => "Subpasta remota", "Access granted" => "Acesso concedido", "Error configuring Dropbox storage" => "Erro ao configurar armazenamento do Dropbox", "Grant access" => "Permitir acesso", "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", -"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.", +"Saved" => "Salvo", +"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", "Delete" => "Excluir", "Enable User External Storage" => "Habilitar Armazenamento Externo do Usuário", -"Allow users to mount their own external storage" => "Permitir usuários a montar seus próprios armazenamentos externos", +"Allow users to mount the following external storage" => "Permitir que usuários montem o seguinte armazenamento externo", "SSL root certificates" => "Certificados SSL raíz", "Import Root Certificate" => "Importar Certificado Raíz" ); diff --git a/apps/files_external/l10n/pt_PT.php b/apps/files_external/l10n/pt_PT.php index 3f2afd33f0..767ddeec8a 100644 --- a/apps/files_external/l10n/pt_PT.php +++ b/apps/files_external/l10n/pt_PT.php @@ -1,27 +1,51 @@ "Local", +"Location" => "Local", +"Amazon S3" => "Amazon S3", +"Key" => "Chave", +"Secret" => "Secreto", +"Access Key" => "Chave de acesso", +"Secret Key" => "Chave Secreta", +"Port (optional)" => "Porta (opcional)", +"Region (optional)" => "Região (opcional)", +"Enable SSL" => "Activar SSL", +"App key" => "Chave da aplicação", +"App secret" => "Chave secreta da aplicação", +"URL" => "URL", +"Username" => "Nome de utilizador", +"Password" => "Palavra-passe", +"Root" => "Raiz", +"Client ID" => "ID Cliente", +"Client secret" => "Segredo do cliente", +"Username (required)" => "Utilizador (requerido)", +"Share" => "Partilhar", +"Remote subfolder" => "Sub-pasta remota ", "Access granted" => "Acesso autorizado", "Error configuring Dropbox storage" => "Erro ao configurar o armazenamento do Dropbox", "Grant access" => "Conceder acesso", "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", -"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.", +"Saved" => "Guardado", +"Note: " => "Aviso: ", +" 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." => "Aviso: O suporte cURL no PHP não está activo ou instalado. Não é possível montar %s. Peça ao seu administrador para instalar.", +"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." => "Aviso: O suporte FTP no PHP não está activo ou instalado. Não é possível montar %s. Peça ao seu administrador para instalar.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Aviso: O cliente\"%s\" não está instalado. Não é possível montar \"%s\" . Peça ao seu administrador para instalar.", "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" => "Não definido", +"No user or group" => "Sem utilizador nem grupo", "All Users" => "Todos os utilizadores", "Groups" => "Grupos", "Users" => "Utilizadores", "Delete" => "Eliminar", "Enable User External Storage" => "Activar Armazenamento Externo para o Utilizador", -"Allow users to mount their own external storage" => "Permitir que os utilizadores montem o seu próprio armazenamento externo", +"Allow users to mount the following external storage" => "Permitir que os utilizadores montem o seguinte armazenamento externo", "SSL root certificates" => "Certificados SSL de raiz", "Import Root Certificate" => "Importar Certificado Root" ); diff --git a/apps/files_external/l10n/ro.php b/apps/files_external/l10n/ro.php index 7115d09ea9..cc48e20ab0 100644 --- a/apps/files_external/l10n/ro.php +++ b/apps/files_external/l10n/ro.php @@ -1,27 +1,28 @@ "Locație", +"URL" => "URL", +"Username" => "Nume utilizator", +"Password" => "Parolă", +"Share" => "Partajează", "Access granted" => "Acces permis", "Error configuring Dropbox storage" => "Eroare la configurarea mediului de stocare Dropbox", "Grant access" => "Permite accesul", "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", -"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!", +"Saved" => "Salvat", "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", "Delete" => "Șterge", "Enable User External Storage" => "Permite stocare externă pentru utilizatori", -"Allow users to mount their own external storage" => "Permite utilizatorilor să monteze stocare externă proprie", +"Allow users to mount the following external storage" => "Permite utilizatorilor să monteze următoarea unitate de stocare", "SSL root certificates" => "Certificate SSL root", "Import Root Certificate" => "Importă certificat root" ); diff --git a/apps/files_external/l10n/ru.php b/apps/files_external/l10n/ru.php index 50c25acba0..be1307a9e6 100644 --- a/apps/files_external/l10n/ru.php +++ b/apps/files_external/l10n/ru.php @@ -1,27 +1,28 @@ "Местоположение", +"URL" => "Ссылка", +"Username" => "Имя пользователя", +"Password" => "Пароль", +"Share" => "Открыть доступ", "Access granted" => "Доступ предоставлен", "Error configuring Dropbox storage" => "Ошибка при настройке хранилища Dropbox", "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 their own 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 cad928acce..908f82d8ee 100644 --- a/apps/files_external/l10n/si_LK.php +++ b/apps/files_external/l10n/si_LK.php @@ -1,5 +1,10 @@ "ස්ථානය", +"URL" => "URL", +"Username" => "පරිශීලක නම", +"Password" => "මුර පදය", +"Share" => "බෙදා හදා ගන්න", "Access granted" => "පිවිසීමට හැක", "Error configuring Dropbox storage" => "Dropbox ගබඩාව වින්‍යාස කිරීමේ දෝශයක් ඇත", "Grant access" => "පිවිසුම ලබාදෙන්න", @@ -9,14 +14,11 @@ $TRANSLATIONS = array( "Folder name" => "ෆොල්ඩරයේ නම", "Configuration" => "වින්‍යාසය", "Options" => "විකල්පයන්", -"Applicable" => "අදාළ", -"None set" => "කිසිවක් නැත", "All Users" => "සියළු පරිශීලකයන්", "Groups" => "කණ්ඩායම්", "Users" => "පරිශීලකයන්", "Delete" => "මකා දමන්න", "Enable User External Storage" => "පරිශීලක භාහිර ගබඩාවන් සක්‍රිය කරන්න", -"Allow users to mount their own external storage" => "පරිශීලකයන්ට තමාගේම භාහිර ගබඩාවන් මවුන්ට් කිරීමේ අයිතිය දෙන්න", "SSL root certificates" => "SSL මූල සහතිකයන්", "Import Root Certificate" => "මූල සහතිකය ආයාත කරන්න" ); diff --git a/apps/files_external/l10n/sk.php b/apps/files_external/l10n/sk.php index 3129cf5c41..03dcc93e7c 100644 --- a/apps/files_external/l10n/sk.php +++ b/apps/files_external/l10n/sk.php @@ -1,5 +1,7 @@ "Poloha", +"Share" => "Zdieľať", "Delete" => "Odstrániť" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/apps/files_external/l10n/sk_SK.php b/apps/files_external/l10n/sk_SK.php index 664d97c43b..e30b007c3c 100644 --- a/apps/files_external/l10n/sk_SK.php +++ b/apps/files_external/l10n/sk_SK.php @@ -1,27 +1,36 @@ "Lokálny", +"Location" => "Umiestnenie", +"URL" => "URL", +"Username" => "Používateľské meno", +"Password" => "Heslo", +"Share" => "Zdieľať", "Access granted" => "Prístup povolený", "Error configuring Dropbox storage" => "Chyba pri konfigurácii úložiska Dropbox", "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é", +"Note: " => "Poznámka: ", +" and " => "a", +"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." => "Poznámka: cURL podpora v PHP nie je zapnutá alebo nainštalovaná. Pripojenie %s nie je možné. Požiadajte správcu systému, aby ju nainštaloval.", +"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." => "Poznámka: FTP podpora v PHP nie je zapnutá alebo nainštalovaná. Pripojenie %s nie je možné. Požiadajte správcu systému, aby ju nainštaloval.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Poznámka: \"%s\" nie je nainštalovaná. Pripojenie %s nie je možné. Požiadajte správcu systému, aby ju nainštaloval.", "External Storage" => "Externé úložisko", "Folder name" => "Názov priečinka", "External storage" => "Externé úložisko", "Configuration" => "Nastavenia", "Options" => "Možnosti", -"Applicable" => "Aplikovateľné", +"Available for" => "K dispozícii pre", "Add storage" => "Pridať úložisko", -"None set" => "Žiadne nastavené", +"No user or group" => "Žiadny používateľ alebo skupina", "All Users" => "Všetci používatelia", "Groups" => "Skupiny", "Users" => "Používatelia", "Delete" => "Zmazať", "Enable User External Storage" => "Povoliť externé úložisko", -"Allow users to mount their own external storage" => "Povoliť používateľom pripojiť si vlastné externé úložisko", +"Allow users to mount the following external storage" => "Povoliť používateľom pripojiť tieto externé úložiská", "SSL root certificates" => "Koreňové SSL certifikáty", "Import Root Certificate" => "Importovať koreňový certifikát" ); diff --git a/apps/files_external/l10n/sl.php b/apps/files_external/l10n/sl.php index b0fcbf9eb6..235ba23eb1 100644 --- a/apps/files_external/l10n/sl.php +++ b/apps/files_external/l10n/sl.php @@ -1,27 +1,38 @@ "Krajevno", +"Location" => "Mesto", +"Amazon S3" => "Amazon S3", +"Key" => "Ključ", +"URL" => "Naslov URL", +"Username" => "Uporabniško ime", +"Password" => "Geslo", +"Share" => "Souporaba", "Access granted" => "Dostop je odobren", "Error configuring Dropbox storage" => "Napaka nastavljanja shrambe Dropbox", "Grant access" => "Odobri dostop", "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", -"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.", +"Saved" => "Shranjeno", +"Note: " => "Opomba: ", +" and " => "in", +"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." => "Opomba: Podpora za naslove cURL v PHP ni omogočena, ali pa ni ustrezno nameščenih programov. Priklapljanje %s ni mogoče. Za pomoč pri namestitvi se obrnite na sistemskega skrbnika.", +"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." => "Opomba: Podpora za protokol FTP v PHP ni omogočena, ali pa ni ustrezno nameščenih programov. Priklapljanje %s ni mogoče. Za pomoč pri namestitvi se obrnite na sistemskega skrbnika.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Opomba: Program \"%s\" ni nameščen. Priklapljanje %s ni mogoče. Za pomoč pri namestitvi se obrnite na sistemskega skrbnika.", "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", "Delete" => "Izbriši", "Enable User External Storage" => "Omogoči zunanjo uporabniško podatkovno shrambo", -"Allow users to mount their own external storage" => "Dovoli uporabnikom priklop lastne zunanje podatkovne shrambe", +"Allow users to mount the following external storage" => "Dovoli uporabnikom priklapljanje navedenih zunanjih shramb.", "SSL root certificates" => "Korenska potrdila SSL", "Import Root Certificate" => "Uvozi korensko potrdilo" ); diff --git a/apps/files_external/l10n/sq.php b/apps/files_external/l10n/sq.php index 328822dcde..563a1b7dd9 100644 --- a/apps/files_external/l10n/sq.php +++ b/apps/files_external/l10n/sq.php @@ -1,5 +1,10 @@ "Vendndodhja", +"URL" => "URL-i", +"Username" => "Përdoruesi", +"Password" => "fjalëkalim", +"Share" => "Ndaj", "Groups" => "Grupet", "Users" => "Përdoruesit", "Delete" => "Elimino" diff --git a/apps/files_external/l10n/sr.php b/apps/files_external/l10n/sr.php index c456daa004..b0276764a8 100644 --- a/apps/files_external/l10n/sr.php +++ b/apps/files_external/l10n/sr.php @@ -1,5 +1,9 @@ "Локација", +"Username" => "Корисничко име", +"Password" => "Лозинка", +"Share" => "Дели", "Groups" => "Групе", "Users" => "Корисници", "Delete" => "Обриши" diff --git a/apps/files_external/l10n/sr@latin.php b/apps/files_external/l10n/sr@latin.php index a2489bbc64..2f17617c11 100644 --- a/apps/files_external/l10n/sr@latin.php +++ b/apps/files_external/l10n/sr@latin.php @@ -1,5 +1,9 @@ "Lokacija", +"Username" => "Korisničko ime", +"Password" => "Lozinka", +"Share" => "Podeli", "Groups" => "Grupe", "Users" => "Korisnici", "Delete" => "Obriši" diff --git a/apps/files_external/l10n/sv.php b/apps/files_external/l10n/sv.php index 2c0b0ab69e..a15ea0ed16 100644 --- a/apps/files_external/l10n/sv.php +++ b/apps/files_external/l10n/sv.php @@ -1,27 +1,36 @@ "Lokal", +"Location" => "Plats", +"URL" => "URL", +"Username" => "Användarnamn", +"Password" => "Lösenord", +"Share" => "Dela", "Access granted" => "Åtkomst beviljad", "Error configuring Dropbox storage" => "Fel vid konfigurering av Dropbox", "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 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 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 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 their own external storage" => "Tillåt användare att montera egen extern lagring", +"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 bb663a4fcb..066cf411dd 100644 --- a/apps/files_external/l10n/ta_LK.php +++ b/apps/files_external/l10n/ta_LK.php @@ -1,5 +1,10 @@ "இடம்", +"URL" => "URL", +"Username" => "பயனாளர் பெயர்", +"Password" => "கடவுச்சொல்", +"Share" => "பகிர்வு", "Access granted" => "அனுமதி வழங்கப்பட்டது", "Error configuring Dropbox storage" => "Dropbox சேமிப்பை தகவமைப்பதில் வழு", "Grant access" => "அனுமதியை வழங்கல்", @@ -9,14 +14,11 @@ $TRANSLATIONS = array( "Folder name" => "கோப்புறை பெயர்", "Configuration" => "தகவமைப்பு", "Options" => "தெரிவுகள்", -"Applicable" => "பயன்படத்தக்க", -"None set" => "தொகுப்பில்லா", "All Users" => "பயனாளர்கள் எல்லாம்", "Groups" => "குழுக்கள்", "Users" => "பயனாளர்", "Delete" => "நீக்குக", "Enable User External Storage" => "பயனாளர் வெளி சேமிப்பை இயலுமைப்படுத்துக", -"Allow users to mount their own external storage" => "பயனாளர் அவர்களுடைய சொந்த வெளியக சேமிப்பை ஏற்ற அனுமதிக்க", "SSL root certificates" => "SSL வேர் சான்றிதழ்கள்", "Import Root Certificate" => "வேர் சான்றிதழை இறக்குமதி செய்க" ); diff --git a/apps/files_external/l10n/te.php b/apps/files_external/l10n/te.php index 7f8d893d46..ee902788a3 100644 --- a/apps/files_external/l10n/te.php +++ b/apps/files_external/l10n/te.php @@ -1,5 +1,7 @@ "వాడుకరి పేరు", +"Password" => "సంకేతపదం", "Folder name" => "సంచయం పేరు", "Users" => "వాడుకరులు", "Delete" => "తొలగించు" diff --git a/apps/files_external/l10n/th_TH.php b/apps/files_external/l10n/th_TH.php index f2ea35f10f..3edf8c6382 100644 --- a/apps/files_external/l10n/th_TH.php +++ b/apps/files_external/l10n/th_TH.php @@ -1,24 +1,24 @@ "ตำแหน่งที่อยู่", +"URL" => "URL", +"Username" => "ชื่อผู้ใช้งาน", +"Password" => "รหัสผ่าน", +"Share" => "แชร์", "Access granted" => "การเข้าถึงได้รับอนุญาตแล้ว", "Error configuring Dropbox storage" => "เกิดข้อผิดพลาดในการกำหนดค่าพื้นที่จัดเก็บข้อมูล Dropbox", "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" => "ผู้ใช้งาน", "Delete" => "ลบ", "Enable User External Storage" => "เปิดให้มีการใช้พื้นที่จัดเก็บข้อมูลของผู้ใช้งานจากภายนอกได้", -"Allow users to mount their own external storage" => "อนุญาตให้ผู้ใช้งานสามารถชี้ตำแหน่งไปที่พื้นที่จัดเก็บข้อมูลภายนอกของตนเองได้", "SSL root certificates" => "ใบรับรองความปลอดภัยด้วยระบบ SSL จาก Root", "Import Root Certificate" => "นำเข้าข้อมูลใบรับรองความปลอดภัยจาก Root" ); diff --git a/apps/files_external/l10n/tr.php b/apps/files_external/l10n/tr.php index 5d5e2b726a..aa3290bd4b 100644 --- a/apps/files_external/l10n/tr.php +++ b/apps/files_external/l10n/tr.php @@ -1,27 +1,68 @@ "Yerel", +"Location" => "Konum", +"Amazon S3" => "Amazon S3", +"Key" => "Anahtar", +"Secret" => "Parola", +"Bucket" => "Bucket", +"Amazon S3 and compliant" => "Amazon S3 ve uyumlu olanlar", +"Access Key" => "Erişim Anahtarı", +"Secret Key" => "Gizli Anahtar", +"Hostname (optional)" => "Makine Adı (isteğe bağlı)", +"Port (optional)" => "Bağl. Nok. (isteğe bağlı)", +"Region (optional)" => "Bölge (isteğe bağlı)", +"Enable SSL" => "SSL'yi Etkinleştir", +"Enable Path Style" => "Yol Biçemini Etkinleştir", +"App key" => "Uyg. anahtarı", +"App secret" => "Uyg. parolası", +"URL" => "URL", +"Username" => "Kullanıcı Adı:", +"Password" => "Parola:", +"Root" => "Kök", +"Secure ftps://" => "Güvenli ftps://", +"Client ID" => "İstemci Kimliğ", +"Client secret" => "İstemci parolası", +"OpenStack Object Storage" => "OpenStack Nesne Depolama", +"Username (required)" => "Kullanıcı adı (gerekli)", +"Bucket (required)" => "Bucket (gerekli)", +"Region (optional for OpenStack Object Storage)" => "Bölge (OpenStack Nesne Depolaması için isteğe bağlı)", +"API Key (required for Rackspace Cloud Files)" => "API Anahtarı (Rackspace Bulut Dosyaları için gerekli)", +"Tenantname (required for OpenStack Object Storage)" => "Kiracı Adı (OpenStack Nesne Depolaması için gerekli)", +"Password (required for OpenStack Object Storage)" => "Parola (OpenStack Nesne Depolaması için gerekli)", +"Service Name (required for OpenStack Object Storage)" => "Hizmet Adı (OpenStack Nesne Depolaması için gerekli)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "Kimlik uç nokta adresi (OpenStack Nesne Depolaması için gerekli)", +"Timeout of HTTP requests in seconds (optional)" => "Saniye cinsinden HTTP istek zaman aşımı (isteğe bağlı)", +"Share" => "Paylaş", +"SMB / CIFS using OC login" => "OC oturumu kullanarak SMB / CIFS", +"Username as share" => "Paylaşım olarak kullanıcı adı", +"Secure https://" => "Güvenli https://", +"Remote subfolder" => "Uzak alt klasör", "Access granted" => "Giriş kabul edildi", "Error configuring Dropbox storage" => "Dropbox depo yapılandırma hatası", "Grant access" => "Erişim sağlandı", "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ı", -"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.", +"Saved" => "Kaydedildi", +"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", "Delete" => "Sil", "Enable User External Storage" => "Kullanıcılar için Harici Depolamayı Etkinleştir", -"Allow users to mount their own external storage" => "Kullanıcıların kendi harici depolamalarını bağlamalarına izin ver", +"Allow users to mount the following external storage" => "Kullanıcıların aşağıdaki harici depolamayı bağlamalarına izin ver", "SSL root certificates" => "SSL kök sertifikaları", "Import Root Certificate" => "Kök Sertifikalarını İçe Aktar" ); diff --git a/apps/files_external/l10n/ug.php b/apps/files_external/l10n/ug.php index ae20f7424d..bd7dc42986 100644 --- a/apps/files_external/l10n/ug.php +++ b/apps/files_external/l10n/ug.php @@ -1,5 +1,10 @@ "ئورنى", +"URL" => "URL", +"Username" => "ئىشلەتكۈچى ئاتى", +"Password" => "ئىم", +"Share" => "ھەمبەھىر", "Folder name" => "قىسقۇچ ئاتى", "External storage" => "سىرتقى ساقلىغۇچ", "Configuration" => "سەپلىمە", diff --git a/apps/files_external/l10n/uk.php b/apps/files_external/l10n/uk.php index e535b455d1..f644fe8606 100644 --- a/apps/files_external/l10n/uk.php +++ b/apps/files_external/l10n/uk.php @@ -1,27 +1,26 @@ "Місце", +"URL" => "URL", +"Username" => "Ім'я користувача", +"Password" => "Пароль", +"Share" => "Поділитися", "Access granted" => "Доступ дозволено", "Error configuring Dropbox storage" => "Помилка при налаштуванні сховища Dropbox", "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" => "Користувачі", "Delete" => "Видалити", "Enable User External Storage" => "Активувати користувацькі зовнішні сховища", -"Allow users to mount their own external storage" => "Дозволити користувачам монтувати власні зовнішні сховища", "SSL root certificates" => "SSL корневі сертифікати", "Import Root Certificate" => "Імпортувати корневі сертифікати" ); diff --git a/apps/files_external/l10n/ur_PK.php b/apps/files_external/l10n/ur_PK.php index 56df17991b..e2138b9046 100644 --- a/apps/files_external/l10n/ur_PK.php +++ b/apps/files_external/l10n/ur_PK.php @@ -1,5 +1,7 @@ "یوزر نیم", +"Password" => "پاسورڈ", "Users" => "یوزرز" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/vi.php b/apps/files_external/l10n/vi.php index da8ac419cd..86d1236f66 100644 --- a/apps/files_external/l10n/vi.php +++ b/apps/files_external/l10n/vi.php @@ -1,27 +1,26 @@ "Vị trí", +"URL" => "URL", +"Username" => "Tên đăng nhập", +"Password" => "Mật khẩu", +"Share" => "Chia sẻ", "Access granted" => "Đã cấp quyền truy cập", "Error configuring Dropbox storage" => "Lỗi cấu hình lưu trữ Dropbox ", "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", "Delete" => "Xóa", "Enable User External Storage" => "Kích hoạt tính năng lưu trữ ngoài", -"Allow users to mount their own external storage" => "Cho phép người dùng kết nối với lưu trữ riêng bên ngoài của họ", "SSL root certificates" => "Chứng chỉ SSL root", "Import Root Certificate" => "Nhập Root Certificate" ); diff --git a/apps/files_external/l10n/zh_CN.php b/apps/files_external/l10n/zh_CN.php index 5e2c2e4fe0..53e76d1dd7 100644 --- a/apps/files_external/l10n/zh_CN.php +++ b/apps/files_external/l10n/zh_CN.php @@ -1,27 +1,44 @@ "本地", +"Location" => "地点", +"Amazon S3" => "Amazon S3", +"Access Key" => "访问密钥", +"Hostname (optional)" => "域名 (可选)", +"Port (optional)" => "端口 (可选)", +"Region (optional)" => "区域 (optional)", +"Enable SSL" => "启用 SSL", +"URL" => "URL", +"Username" => "用户名", +"Password" => "密码", +"Root" => "根路径", +"Secure ftps://" => "安全 ftps://", +"Share" => "共享", +"SMB / CIFS using OC login" => "SMB / CIFS 使用 OC 登录信息", +"Secure https://" => "安全 https://", +"Remote subfolder" => "远程子文件夹", "Access granted" => "权限已授予。", "Error configuring Dropbox storage" => "配置Dropbox存储时出错", "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 不能挂载。请请求您的系统管理员安装该它。", +"Saved" => "已保存", +"Note: " => "注意:", +" and " => "和", "External Storage" => "外部存储", "Folder name" => "目录名称", "External storage" => "外部存储", "Configuration" => "配置", "Options" => "选项", -"Applicable" => "适用的", +"Available for" => "可用于", "Add storage" => "添加存储", -"None set" => "未设置", +"No user or group" => "无用户或组", "All Users" => "所有用户", "Groups" => "组", "Users" => "用户", "Delete" => "删除", "Enable User External Storage" => "启用用户外部存储", -"Allow users to mount their own external storage" => "允许用户挂载自有外部存储", +"Allow users to mount the following external storage" => "允许用户挂载以下外部存储", "SSL root certificates" => "SSL根证书", "Import Root Certificate" => "导入根证书" ); diff --git a/apps/files_external/l10n/zh_HK.php b/apps/files_external/l10n/zh_HK.php index 76e0ed69d2..b3a22c91bb 100644 --- a/apps/files_external/l10n/zh_HK.php +++ b/apps/files_external/l10n/zh_HK.php @@ -1,5 +1,10 @@ "網址", +"Username" => "用戶名稱", +"Password" => "密碼", +"Share" => "分享", +"Folder name" => "資料夾名稱", "Groups" => "群組", "Users" => "用戶", "Delete" => "刪除" diff --git a/apps/files_external/l10n/zh_TW.php b/apps/files_external/l10n/zh_TW.php index d85d18a1c3..a4b0ebe4dd 100644 --- a/apps/files_external/l10n/zh_TW.php +++ b/apps/files_external/l10n/zh_TW.php @@ -1,27 +1,28 @@ "本地", +"Location" => "地點", +"URL" => "URL", +"Username" => "使用者名稱:", +"Password" => "密碼", +"Share" => "分享", "Access granted" => "允許存取", "Error configuring Dropbox storage" => "設定 Dropbox 儲存時發生錯誤", "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 分享,請洽您的系統管理員將其安裝並啓用。", +"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 their own external storage" => "允許使用者自行掛載他們的外部儲存", "SSL root certificates" => "SSL 根憑證", "Import Root Certificate" => "匯入根憑證" ); diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 06ccd5d16f..2093fb7e58 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 b2109e5eac..99eca2f38c 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -4,6 +4,8 @@ * * @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 @@ -19,15 +21,52 @@ * License along with this library. If not, see . */ +set_include_path( + get_include_path() . PATH_SEPARATOR . + \OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib' +); + /** -* Class to configure the config/mount.php and data/$user/mount.php files -*/ + * Class to configure mount.json globally and for users + */ class OC_Mount_Config { + // TODO: make this class non-static and give it a proper namespace const MOUNT_TYPE_GLOBAL = 'global'; const MOUNT_TYPE_GROUP = 'group'; const MOUNT_TYPE_USER = 'user'; + // 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 @@ -35,124 +74,157 @@ 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() { + $sortFunc = function($a, $b) { + return strcasecmp($a['backend'], $b['backend']); + }; - $backends['\OC\Files\Storage\Local']=array( - 'backend' => 'Local', - 'configuration' => array( - 'datadir' => 'Location')); + $backEnds = array(); - $backends['\OC\Files\Storage\AmazonS3']=array( - 'backend' => 'Amazon S3', - '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')); + 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; + } - $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'); + uasort($backEnds, $sortFunc); - 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://')); + return $backEnds; + } - 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'); + /** + * Hook that mounts the given user's visible mount points + * @param array $data + */ + public static function initMountPointsHook($data) { + $mountPoints = self::getAbsoluteMountPoints($data['user']); + foreach ($mountPoints as $mountPoint => $options) { + \OC\Files\Filesystem::mount($options['class'], $options['options'], $mountPoint); + } + } - 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)', - ) - ); - } + /** + * Returns the mount points for the given user. + * The mount point is relative to the data directory. + * + * @param string $user user + * @return array of mount point string as key, mountpoint config as value + */ + public static function getAbsoluteMountPoints($user) { + $mountPoints = array(); - 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')); + $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data"); + $mount_file = \OC_Config::getValue("mount_file", $datadir . "/mount.json"); + + //move config file to it's new position + if (is_file(\OC::$SERVERROOT . '/config/mount.json')) { + rename(\OC::$SERVERROOT . '/config/mount.json', $mount_file); + } + + // Load system mount points + $mountConfig = self::readData(false); + if (isset($mountConfig[self::MOUNT_TYPE_GLOBAL])) { + foreach ($mountConfig[self::MOUNT_TYPE_GLOBAL] as $mountPoint => $options) { + $options['options'] = self::decryptPasswords($options['options']); + $mountPoints[$mountPoint] = $options; + } + } + if (isset($mountConfig[self::MOUNT_TYPE_GROUP])) { + foreach ($mountConfig[self::MOUNT_TYPE_GROUP] as $group => $mounts) { + if (\OC_Group::inGroup($user, $group)) { + foreach ($mounts as $mountPoint => $options) { + $mountPoint = self::setUserVars($user, $mountPoint); + foreach ($options as &$option) { + $option = self::setUserVars($user, $option); + } + $options['options'] = self::decryptPasswords($options['options']); + $mountPoints[$mountPoint] = $options; + } + } + } + } + if (isset($mountConfig[self::MOUNT_TYPE_USER])) { + foreach ($mountConfig[self::MOUNT_TYPE_USER] as $mountUser => $mounts) { + if ($mountUser === 'all' or strtolower($mountUser) === strtolower($user)) { + foreach ($mounts as $mountPoint => $options) { + $mountPoint = self::setUserVars($user, $mountPoint); + foreach ($options as &$option) { + $option = self::setUserVars($user, $option); + } + $options['options'] = self::decryptPasswords($options['options']); + $mountPoints[$mountPoint] = $options; + } + } } } - 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://')); + // Load personal mount points + $mountConfig = self::readData(true); + if (isset($mountConfig[self::MOUNT_TYPE_USER][$user])) { + foreach ($mountConfig[self::MOUNT_TYPE_USER][$user] as $mountPoint => $options) { + $options['options'] = self::decryptPasswords($options['options']); + $mountPoints[$mountPoint] = $options; + } } - $backends['\OC\Files\Storage\SFTP']=array( - 'backend' => 'SFTP', - 'configuration' => array( - 'host' => 'URL', - 'user' => 'Username', - 'password' => '*Password', - 'root' => '&Root')); + return $mountPoints; + } - $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')); + /** + * fill in the correct values for $user + * + * @param string $user + * @param string $input + * @return string + */ + private static function setUserVars($user, $input) { + return str_replace('$user', $user, $input); + } - return($backends); + + /** + * Get details on each of the external storage backends, used for the mount config UI + * Some backends are not available as a personal backend, f.e. Local and such that have + * been disabled by the admin. + * + * If a custom UI is needed, add the key 'custom' and a javascript file with that name will be loaded + * If the configuration parameter should be secret, add a '*' to the beginning of the value + * 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 array + */ + public static function getPersonalBackends() { + + // 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']); + + $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; } /** @@ -171,20 +243,26 @@ class OC_Mount_Config { if (strpos($mount['class'], 'OC_Filestorage_') !== false) { $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } + $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; } } } @@ -196,25 +274,30 @@ class OC_Mount_Config { if (strpos($mount['class'], 'OC_Filestorage_') !== false) { $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } + $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); } /** @@ -224,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])) { @@ -233,26 +316,37 @@ class OC_Mount_Config { if (strpos($mount['class'], 'OC_Filestorage_') !== false) { $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } - // Remove '/uid/files/' from mount point - $personal[substr($mountPoint, strlen($uid) + 8)] = array( + $mount['options'] = self::decryptPasswords($mount['options']); + $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) ); } } return $personal; } - private static function getBackendStatus($class, $options) { + /** + * Test connecting using the given backend configuration + * @param string $class backend class name + * @param array $options backend configuration options + * @return bool true if the connection succeeded, false otherwise + */ + private static function getBackendStatus($class, $options, $isPersonal) { + if (self::$skipTest) { + return true; + } foreach ($options as &$option) { - $option = str_replace('$user', OCP\User::getUser(), $option); + $option = self::setUserVars(OCP\User::getUser(), $option); } 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; @@ -277,22 +371,35 @@ class OC_Mount_Config { $mountType, $applicable, $isPersonal = false) { + $backends = self::getBackends(); $mountPoint = OC\Files\Filesystem::normalizePath($mountPoint); - if ($mountPoint === '' || $mountPoint === '/' || $mountPoint == '/Shared') { - // can't mount at root or "Shared" folder + if ($mountPoint === '' || $mountPoint === '/') { + // can't mount at root folder + return false; + } + + if (!isset($backends[$class])) { + // invalid backend return false; } if ($isPersonal) { // Verify that the mount point applies for the current user - // Prevent non-admin users from mounting local storage - if ($applicable != OCP\User::getUser() || $class == '\OC\Files\Storage\Local') { + // Prevent non-admin users from mounting local storage and other disabled backends + $allowed_backends = self::getPersonalBackends(); + if ($applicable != OCP\User::getUser() || !isset($allowed_backends[$class])) { return false; } $mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/'); } else { $mountPoint = '/$user/files/'.ltrim($mountPoint, '/'); } - $mount = array($applicable => array($mountPoint => array('class' => $class, 'options' => $classOptions))); + + $mount = array($applicable => array( + $mountPoint => array( + 'class' => $class, + 'options' => self::encryptPasswords($classOptions)) + ) + ); $mountPoints = self::readData($isPersonal); // Merge the new mount point into the current mount points if (isset($mountPoints[$mountType])) { @@ -306,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); } /** @@ -353,7 +460,8 @@ class OC_Mount_Config { $jsonFile = OC_User::getHome(OCP\User::getUser()).'/mount.json'; } else { $phpFile = OC::$SERVERROOT.'/config/mount.php'; - $jsonFile = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json"); + $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/'); + $jsonFile = \OC_Config::getValue('mount_file', $datadir . '/mount.json'); } if (is_file($jsonFile)) { $mountPoints = json_decode(file_get_contents($jsonFile), true); @@ -379,9 +487,15 @@ class OC_Mount_Config { if ($isPersonal) { $file = OC_User::getHome(OCP\User::getUser()).'/mount.json'; } else { - $file = \OC_Config::getValue("mount_file", \OC::$SERVERROOT . "/data/mount.json"); + $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/'); + $file = \OC_Config::getValue('mount_file', $datadir . '/mount.json'); } - $content = json_encode($data); + $options = 0; + if (defined('JSON_PRETTY_PRINT')) { + // only for PHP >= 5.4 + $options = JSON_PRETTY_PRINT; + } + $content = json_encode($data, $options); @file_put_contents($file, $content); @chmod($file, 0640); } @@ -433,54 +547,174 @@ class OC_Mount_Config { return true; } - /** - * check if smbclient is installed - */ - public static function checksmbclient() { - if(function_exists('shell_exec')) { - $output=shell_exec('which smbclient 2> /dev/null'); - return !empty($output); - }else{ - return false; - } - } - - /** - * check if php-ftp is installed - */ - public static function checkphpftp() { - if(function_exists('ftp_login')) { - return true; - }else{ - return false; - } - } - - /** - * check if curl is installed - */ - public static function checkcurl() { - return function_exists('curl_init'); - } - /** * check dependencies */ 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.').'
'; + $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(!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.').'
'; + + if (count($dependencies) > 0) { + return OC_Mount_Config::generateDependencyMessage($dependencies); } - 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 ''; + } + + private static function addDependency(&$dependencies, $module, $backend, $message=null) { + if (!isset($dependencies[$module])) { + $dependencies[$module] = array(); } - return $txt; + if ($message === null) { + $dependencies[$module][] = $backend; + } else { + $dependencies[$module][] = array('backend' => $backend, 'message' => $message); + } + } + + 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; + } + + /** + * Returns a dependency missing message + * @param $l OC_L10N + * @param $module string + * @param $backend string + * @return string + */ + 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)); + } + } + + /** + * Encrypt passwords in the given config options + * @param array $options mount options + * @return array updated options + */ + private static function encryptPasswords($options) { + if (isset($options['password'])) { + $options['password_encrypted'] = self::encryptPassword($options['password']); + // do not unset the password, we want to keep the keys order + // on load... because that's how the UI currently works + $options['password'] = ''; + } + return $options; + } + + /** + * Decrypt passwords in the given config options + * @param array $options mount options + * @return array updated options + */ + private static function decryptPasswords($options) { + // note: legacy options might still have the unencrypted password in the "password" field + if (isset($options['password_encrypted'])) { + $options['password'] = self::decryptPassword($options['password_encrypted']); + unset($options['password_encrypted']); + } + return $options; + } + + /** + * Encrypt a single password + * @param string $password plain text password + * @return encrypted password + */ + private static function encryptPassword($password) { + $cipher = self::getCipher(); + $iv = \OCP\Util::generateRandomBytes(16); + $cipher->setIV($iv); + return base64_encode($iv . $cipher->encrypt($password)); + } + + /** + * Decrypts a single password + * @param string $encryptedPassword encrypted password + * @return plain text password + */ + private static function decryptPassword($encryptedPassword) { + $cipher = self::getCipher(); + $binaryPassword = base64_decode($encryptedPassword); + $iv = substr($binaryPassword, 0, 16); + $cipher->setIV($iv); + $binaryPassword = substr($binaryPassword, 16); + return $cipher->decrypt($binaryPassword); + } + + /** + * Returns the encryption cipher + */ + private static function getCipher() { + if (!class_exists('Crypt_AES', false)) { + include('Crypt/AES.php'); + } + $cipher = new Crypt_AES(CRYPT_AES_MODE_CBC); + $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 0214e18020..38de3360f2 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 00bf7a189c..b3f8b1444a 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 35457f6852..56c0d45165 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/irods.php b/apps/files_external/lib/irods.php deleted file mode 100644 index 7a7e900fbf..0000000000 --- a/apps/files_external/lib/irods.php +++ /dev/null @@ -1,155 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -namespace OC\Files\Storage; - -set_include_path(get_include_path() . PATH_SEPARATOR . - \OC_App::getAppPath('files_external') . '/3rdparty/irodsphp/prods/src'); - -ob_start(); -require_once 'ProdsConfig.inc.php'; -require_once 'ProdsStreamer.class.php'; -ob_end_clean(); - -class iRODS extends \OC\Files\Storage\StreamWrapper{ - private $password; - private $user; - private $host; - private $port; - private $zone; - private $root; - private $use_logon_credentials; - private $auth_mode; - - public function __construct($params) { - if (isset($params['host'])) { - $this->host = $params['host']; - $this->port = isset($params['port']) ? $params['port'] : 1247; - $this->user = isset($params['user']) ? $params['user'] : ''; - $this->password = isset($params['password']) ? $params['password'] : ''; - $this->use_logon_credentials = ($params['use_logon_credentials'] === 'true'); - $this->zone = $params['zone']; - $this->auth_mode = isset($params['auth_mode']) ? $params['auth_mode'] : ''; - - $this->root = isset($params['root']) ? $params['root'] : '/'; - if ( ! $this->root || $this->root[0] !== '/') { - $this->root='/'.$this->root; - } - - // take user and password from the session - if ($this->use_logon_credentials && \OC::$session->exists('irods-credentials')) - { - $params = \OC::$session->get('irods-credentials'); - $this->user = $params['uid']; - $this->password = $params['password']; - } - - //create the root folder if necessary - if ( ! $this->is_dir('')) { - $this->mkdir(''); - } - } else { - throw new \Exception(); - } - - } - - public static function login( $params ) { - \OC::$session->set('irods-credentials', $params); - } - - public function getId(){ - return 'irods::' . $this->user . '@' . $this->host . '/' . $this->root; - } - - /** - * construct the rods url - * @param string $path - * @return string - */ - public function constructUrl($path) { - $path = rtrim($path,'/'); - if ( $path === '' || $path[0] !== '/') { - $path = '/'.$path; - } - - // adding auth method - $userWithZone = $this->user.'.'.$this->zone; - if ($this->auth_mode !== '') { - $userWithZone .= '.'.$this->auth_mode; - } - - // url wrapper schema is named rods - return 'rods://'.$userWithZone.':'.$this->password.'@'.$this->host.':'.$this->port.$this->root.$path; - } - - public function filetype($path) { - return @filetype($this->constructUrl($path)); - } - - public function mkdir($path) { - return @mkdir($this->constructUrl($path)); - } - - public function touch($path, $mtime=null) { - - // we cannot set a time - if ($mtime != null) { - return false; - } - - $path = $this->constructUrl($path); - - // if the file doesn't exist we create it - if (!file_exists($path)) { - file_put_contents($path, ''); - return true; - } - - // mtime updates are not supported - return false; - } - - /** - * check if a file or folder has been updated since $time - * @param string $path - * @param int $time - * @return bool - */ - public function hasUpdated($path,$time) { - // this it a work around for folder mtimes -> we loop it's content - if ( $this->is_dir($path)) { - $actualTime=$this->collectionMTime($path); - return $actualTime>$time; - } - - $actualTime=$this->filemtime($path); - return $actualTime>$time; - } - - /** - * get the best guess for the modification time of an iRODS collection - * @param string $path - */ - private function collectionMTime($path) { - $dh = $this->opendir($path); - $lastCTime = $this->filemtime($path); - if(is_resource($dh)) { - while (($file = readdir($dh)) !== false) { - if ($file != '.' and $file != '..') { - $time = $this->filemtime($file); - if ($time > $lastCTime) { - $lastCTime = $time; - } - } - } - } - return $lastCTime; - } - -} diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index c5fba92ee6..b1d355323d 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -37,7 +37,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ $this->share = substr($this->share, 0, -1); } } else { - throw new \Exception(); + throw new \Exception('Invalid configuration'); } } @@ -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 0000000000..0c79c06c5d --- /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 7a56fcfc8b..a202d3843c 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 9afe73aebd..dc98dcfb80 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -8,7 +8,7 @@ namespace OC\Files\Storage; -class DAV extends \OC\Files\Storage\Common{ +class DAV extends \OC\Files\Storage\Common { private $password; private $user; private $host; @@ -21,7 +21,7 @@ class DAV extends \OC\Files\Storage\Common{ */ private $client; - private static $tempFiles=array(); + private static $tempFiles = array(); public function __construct($params) { if (isset($params['host']) && isset($params['user']) && isset($params['password'])) { @@ -29,9 +29,9 @@ class DAV extends \OC\Files\Storage\Common{ //remove leading http[s], will be generated in createBaseUri() if (substr($host, 0, 8) == "https://") $host = substr($host, 8); else if (substr($host, 0, 7) == "http://") $host = substr($host, 7); - $this->host=$host; - $this->user=$params['user']; - $this->password=$params['password']; + $this->host = $host; + $this->user = $params['user']; + $this->password = $params['password']; if (isset($params['secure'])) { if (is_string($params['secure'])) { $this->secure = ($params['secure'] === 'true'); @@ -42,25 +42,25 @@ class DAV extends \OC\Files\Storage\Common{ $this->secure = false; } if ($this->secure === true) { - $certPath=\OC_User::getHome(\OC_User::getUser()) . '/files_external/rootcerts.crt'; + $certPath = \OC_User::getHome(\OC_User::getUser()) . '/files_external/rootcerts.crt'; if (file_exists($certPath)) { - $this->certPath=$certPath; + $this->certPath = $certPath; } } - $this->root=isset($params['root'])?$params['root']:'/'; - if ( ! $this->root || $this->root[0]!='/') { - $this->root='/'.$this->root; + $this->root = isset($params['root']) ? $params['root'] : '/'; + if (!$this->root || $this->root[0] != '/') { + $this->root = '/' . $this->root; } - if (substr($this->root, -1, 1)!='/') { - $this->root.='/'; + if (substr($this->root, -1, 1) != '/') { + $this->root .= '/'; } } else { throw new \Exception(); } } - private function init(){ - if($this->ready) { + private function init() { + if ($this->ready) { return; } $this->ready = true; @@ -78,28 +78,28 @@ class DAV extends \OC\Files\Storage\Common{ } } - public function getId(){ + public function getId() { return 'webdav::' . $this->user . '@' . $this->host . '/' . $this->root; } protected function createBaseUri() { - $baseUri='http'; + $baseUri = 'http'; if ($this->secure) { - $baseUri.='s'; + $baseUri .= 's'; } - $baseUri.='://'.$this->host.$this->root; + $baseUri .= '://' . $this->host . $this->root; return $baseUri; } public function mkdir($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); return $this->simpleResponse('MKCOL', $path, null, 201); } public function rmdir($path) { $this->init(); - $path=$this->cleanPath($path) . '/'; + $path = $this->cleanPath($path) . '/'; // FIXME: some WebDAV impl return 403 when trying to DELETE // a non-empty folder return $this->simpleResponse('DELETE', $path, null, 204); @@ -107,35 +107,35 @@ class DAV extends \OC\Files\Storage\Common{ public function opendir($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { - $response=$this->client->propfind($this->encodePath($path), array(), 1); - $id=md5('webdav'.$this->root.$path); + $response = $this->client->propfind($this->encodePath($path), array(), 1); + $id = md5('webdav' . $this->root . $path); $content = array(); - $files=array_keys($response); - array_shift($files);//the first entry is the current directory + $files = array_keys($response); + array_shift($files); //the first entry is the current directory foreach ($files as $file) { $file = urldecode(basename($file)); - $content[]=$file; + $content[] = $file; } \OC\Files\Stream\Dir::register($id, $content); - return opendir('fakedir://'.$id); - } catch(\Exception $e) { + return opendir('fakedir://' . $id); + } catch (\Exception $e) { return false; } } public function filetype($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { - $response=$this->client->propfind($this->encodePath($path), array('{DAV:}resourcetype')); + $response = $this->client->propfind($this->encodePath($path), array('{DAV:}resourcetype')); $responseType = array(); if (isset($response["{DAV:}resourcetype"])) { - $responseType=$response["{DAV:}resourcetype"]->resourceType; + $responseType = $response["{DAV:}resourcetype"]->resourceType; } - return (count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; - } catch(\Exception $e) { + return (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file'; + } catch (\Exception $e) { error_log($e->getMessage()); \OCP\Util::writeLog("webdav client", \OCP\Util::sanitizeHTML($e->getMessage()), \OCP\Util::ERROR); return false; @@ -144,11 +144,11 @@ class DAV extends \OC\Files\Storage\Common{ public function file_exists($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { $this->client->propfind($this->encodePath($path), array('{DAV:}resourcetype')); - return true;//no 404 exception - } catch(\Exception $e) { + return true; //no 404 exception + } catch (\Exception $e) { return false; } } @@ -160,34 +160,34 @@ class DAV extends \OC\Files\Storage\Common{ public function fopen($path, $mode) { $this->init(); - $path=$this->cleanPath($path); - switch($mode) { + $path = $this->cleanPath($path); + switch ($mode) { case 'r': case 'rb': - if ( ! $this->file_exists($path)) { + if (!$this->file_exists($path)) { return false; } //straight up curl instead of sabredav here, sabredav put's the entire get result in memory $curl = curl_init(); $fp = fopen('php://temp', 'r+'); - curl_setopt($curl, CURLOPT_USERPWD, $this->user.':'.$this->password); - curl_setopt($curl, CURLOPT_URL, $this->createBaseUri().$this->encodePath($path)); + curl_setopt($curl, CURLOPT_USERPWD, $this->user . ':' . $this->password); + curl_setopt($curl, CURLOPT_URL, $this->createBaseUri() . $this->encodePath($path)); curl_setopt($curl, CURLOPT_FILE, $fp); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); if ($this->secure === true) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); - if($this->certPath){ + if ($this->certPath) { curl_setopt($curl, CURLOPT_CAINFO, $this->certPath); } } - - curl_exec ($curl); + + curl_exec($curl); $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($statusCode !== 200) { \OCP\Util::writeLog("webdav client", 'curl GET ' . curl_getinfo($curl, CURLINFO_EFFECTIVE_URL) . ' returned status code ' . $statusCode, \OCP\Util::ERROR); } - curl_close ($curl); + curl_close($curl); rewind($fp); return $fp; case 'w': @@ -203,18 +203,19 @@ class DAV extends \OC\Files\Storage\Common{ case 'c': case 'c+': //emulate these - if (strrpos($path, '.')!==false) { - $ext=substr($path, strrpos($path, '.')); + if (strrpos($path, '.') !== false) { + $ext = substr($path, strrpos($path, '.')); } else { - $ext=''; + $ext = ''; + } + if ($this->file_exists($path)) { + $tmpFile = $this->getCachedFile($path); + } else { + $tmpFile = \OCP\Files::tmpFile($ext); } - $tmpFile = \OCP\Files::tmpFile($ext); \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); - if($this->file_exists($path)) { - $this->getFile($path, $tmpFile); - } - self::$tempFiles[$tmpFile]=$path; - return fopen('close://'.$tmpFile, $mode); + self::$tempFiles[$tmpFile] = $path; + return fopen('close://' . $tmpFile, $mode); } } @@ -227,32 +228,31 @@ class DAV extends \OC\Files\Storage\Common{ public function free_space($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { - $response=$this->client->propfind($this->encodePath($path), array('{DAV:}quota-available-bytes')); + $response = $this->client->propfind($this->encodePath($path), array('{DAV:}quota-available-bytes')); if (isset($response['{DAV:}quota-available-bytes'])) { return (int)$response['{DAV:}quota-available-bytes']; } else { return \OC\Files\SPACE_UNKNOWN; } - } catch(\Exception $e) { + } catch (\Exception $e) { return \OC\Files\SPACE_UNKNOWN; } } - public function touch($path, $mtime=null) { + public function touch($path, $mtime = null) { $this->init(); if (is_null($mtime)) { - $mtime=time(); + $mtime = time(); } - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); // if file exists, update the mtime, else create a new empty file if ($this->file_exists($path)) { try { $this->client->proppatch($this->encodePath($path), array('{DAV:}lastmodified' => $mtime)); - } - catch (\Sabre_DAV_Exception_NotImplemented $e) { + } catch (\Sabre_DAV_Exception_NotImplemented $e) { return false; } } else { @@ -261,23 +261,13 @@ class DAV extends \OC\Files\Storage\Common{ return true; } - /** - * @param string $path - * @param string $target - */ - public function getFile($path, $target) { + protected function uploadFile($path, $target) { $this->init(); - $source=$this->fopen($path, 'r'); - file_put_contents($target, $source); - } - - public function uploadFile($path, $target) { - $this->init(); - $source=fopen($path, 'r'); + $source = fopen($path, 'r'); $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_USERPWD, $this->user . ':' . $this->password); + 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)); @@ -285,26 +275,29 @@ class DAV extends \OC\Files\Storage\Common{ if ($this->secure === true) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); - if($this->certPath){ + if ($this->certPath) { curl_setopt($curl, CURLOPT_CAINFO, $this->certPath); } } - curl_exec ($curl); + curl_exec($curl); $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ($statusCode !== 200) { \OCP\Util::writeLog("webdav client", 'curl GET ' . curl_getinfo($curl, CURLINFO_EFFECTIVE_URL) . ' returned status code ' . $statusCode, \OCP\Util::ERROR); } - curl_close ($curl); + curl_close($curl); + $this->removeCachedFile($target); } public function rename($path1, $path2) { $this->init(); $path1 = $this->encodePath($this->cleanPath($path1)); - $path2 = $this->createBaseUri().$this->encodePath($this->cleanPath($path2)); + $path2 = $this->createBaseUri() . $this->encodePath($this->cleanPath($path2)); try { - $this->client->request('MOVE', $path1, null, array('Destination'=>$path2)); + $this->client->request('MOVE', $path1, null, array('Destination' => $path2)); + $this->removeCachedFile($path1); + $this->removeCachedFile($path2); return true; - } catch(\Exception $e) { + } catch (\Exception $e) { return false; } } @@ -312,47 +305,48 @@ class DAV extends \OC\Files\Storage\Common{ public function copy($path1, $path2) { $this->init(); $path1 = $this->encodePath($this->cleanPath($path1)); - $path2 = $this->createBaseUri().$this->encodePath($this->cleanPath($path2)); + $path2 = $this->createBaseUri() . $this->encodePath($this->cleanPath($path2)); try { - $this->client->request('COPY', $path1, null, array('Destination'=>$path2)); + $this->client->request('COPY', $path1, null, array('Destination' => $path2)); + $this->removeCachedFile($path2); return true; - } catch(\Exception $e) { + } catch (\Exception $e) { return false; } } public function stat($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { $response = $this->client->propfind($this->encodePath($path), array('{DAV:}getlastmodified', '{DAV:}getcontentlength')); return array( - 'mtime'=>strtotime($response['{DAV:}getlastmodified']), - 'size'=>(int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0, + 'mtime' => strtotime($response['{DAV:}getlastmodified']), + 'size' => (int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0, ); - } catch(\Exception $e) { + } catch (\Exception $e) { return array(); } } public function getMimeType($path) { $this->init(); - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { - $response=$this->client->propfind($this->encodePath($path), array('{DAV:}getcontenttype', '{DAV:}resourcetype')); + $response = $this->client->propfind($this->encodePath($path), array('{DAV:}getcontenttype', '{DAV:}resourcetype')); $responseType = array(); if (isset($response["{DAV:}resourcetype"])) { - $responseType=$response["{DAV:}resourcetype"]->resourceType; + $responseType = $response["{DAV:}resourcetype"]->resourceType; } - $type=(count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; - if ($type=='dir') { + $type = (count($responseType) > 0 and $responseType[0] == "{DAV:}collection") ? 'dir' : 'file'; + if ($type == 'dir') { return 'httpd/unix-directory'; } elseif (isset($response['{DAV:}getcontenttype'])) { return $response['{DAV:}getcontenttype']; } else { return false; } - } catch(\Exception $e) { + } catch (\Exception $e) { return false; } } @@ -368,6 +362,7 @@ class DAV extends \OC\Files\Storage\Common{ /** * URL encodes the given path but keeps the slashes + * * @param string $path to encode * @return string encoded path */ @@ -382,13 +377,24 @@ class DAV extends \OC\Files\Storage\Common{ * @param integer $expected */ private function simpleResponse($method, $path, $body, $expected) { - $path=$this->cleanPath($path); + $path = $this->cleanPath($path); try { - $response=$this->client->request($method, $this->encodePath($path), $body); - return $response['statusCode']==$expected; - } catch(\Exception $e) { + $response = $this->client->request($method, $this->encodePath($path), $body); + return $response['statusCode'] == $expected; + } catch (\Exception $e) { 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/personal.php b/apps/files_external/personal.php index 90f5e15953..90d7afed28 100755 --- a/apps/files_external/personal.php +++ b/apps/files_external/personal.php @@ -22,9 +22,8 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addStyle('files_external', 'settings'); -$backends = OC_Mount_Config::getBackends(); -// Remove local storage -unset($backends['\OC\Files\Storage\Local']); +$backends = OC_Mount_Config::getPersonalBackends(); + $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('isAdminPage', false); $tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints()); diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php index 31183409e3..5b62b54220 100644 --- a/apps/files_external/settings.php +++ b/apps/files_external/settings.php @@ -26,10 +26,26 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addscript('3rdparty', 'chosen/chosen.jquery.min'); OCP\Util::addStyle('files_external', 'settings'); OCP\Util::addStyle('3rdparty', 'chosen/chosen'); + +$backends = OC_Mount_Config::getBackends(); +$personal_backends = array(); +$enabled_backends = explode(',', OCP\Config::getAppValue('files_external', 'user_mounting_backends', '')); +foreach ($backends as $class => $backend) +{ + if ($class != '\OC\Files\Storage\Local') + { + $personal_backends[$class] = array( + 'backend' => $backend['backend'], + 'enabled' => in_array($class, $enabled_backends), + ); + } +} + $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('isAdminPage', true); $tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints()); -$tmpl->assign('backends', OC_Mount_Config::getBackends()); +$tmpl->assign('backends', $backends); +$tmpl->assign('personal_backends', $personal_backends); $tmpl->assign('groups', OC_Group::getGroups()); $tmpl->assign('users', OCP\User::getUsers()); $tmpl->assign('userDisplayNames', OC_User::getDisplayNames()); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 3ca16c3c7a..df80ed1099 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -1,143 +1,152 @@ -
-
+

t('External Storage')); ?>

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

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

+
-
-

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

'> @@ -157,6 +166,5 @@ - diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php index 767c0adf58..62aff4d1bc 100644 --- a/apps/files_external/tests/config.php +++ b/apps/files_external/tests/config.php @@ -28,7 +28,7 @@ return array( 'wait'=> 0 ), 'owncloud'=>array( - 'run'=>true, + 'run'=>false, 'host'=>'localhost/owncloud', 'user'=>'test', 'password'=>'test', diff --git a/apps/files_external/tests/dynamicmountconfig.php b/apps/files_external/tests/dynamicmountconfig.php new file mode 100644 index 0000000000..650299075e --- /dev/null +++ b/apps/files_external/tests/dynamicmountconfig.php @@ -0,0 +1,101 @@ + + * + * 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'; + +/** + * 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/irods.php b/apps/files_external/tests/irods.php deleted file mode 100644 index 6aa9d3a3b0..0000000000 --- a/apps/files_external/tests/irods.php +++ /dev/null @@ -1,32 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -namespace Test\Files\Storage; - -class iRODS extends Storage { - - protected $backupGlobals = FALSE; - - private $config; - - public function setUp() { - $id = uniqid(); - $this->config = include('files_external/tests/config.php'); - if ( ! is_array($this->config) or ! isset($this->config['irods']) or ! $this->config['irods']['run']) { - $this->markTestSkipped('irods backend not configured'); - } - $this->config['irods']['root'] .= $id; //make sure we have an new empty folder to work in - $this->instance = new \OC\Files\Storage\iRODS($this->config['irods']); - } - - public function tearDown() { - if ($this->instance) { - \OCP\Files::rmdirr($this->instance->constructUrl('')); - } - } -} diff --git a/apps/files_external/tests/mountconfig.php b/apps/files_external/tests/mountconfig.php index 941aec680b..14fe1d90b7 100644 --- a/apps/files_external/tests/mountconfig.php +++ b/apps/files_external/tests/mountconfig.php @@ -22,8 +22,6 @@ require_once __DIR__ . '/../../../lib/base.php'; -require __DIR__ . '/../lib/config.php'; - class Test_Mount_Config_Dummy_Storage { public function test() { return true; @@ -34,6 +32,90 @@ class Test_Mount_Config_Dummy_Storage { * Class Test_Mount_Config */ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { + + private $dataDir; + private $userHome; + private $oldAllowedBackends; + private $allBackends; + + const TEST_USER1 = 'user1'; + const TEST_USER2 = 'user2'; + const TEST_GROUP1 = 'group1'; + const TEST_GROUP2 = 'group2'; + + public function setUp() { + \OC_User::createUser(self::TEST_USER1, self::TEST_USER1); + \OC_User::createUser(self::TEST_USER2, self::TEST_USER2); + + \OC_Group::createGroup(self::TEST_GROUP1); + \OC_Group::addToGroup(self::TEST_USER1, self::TEST_GROUP1); + \OC_Group::createGroup(self::TEST_GROUP2); + \OC_Group::addToGroup(self::TEST_USER2, self::TEST_GROUP2); + + \OC_User::setUserId(self::TEST_USER1); + $this->userHome = \OC_User::getHome(self::TEST_USER1); + mkdir($this->userHome); + + $this->dataDir = \OC_Config::getValue( + 'datadirectory', + \OC::$SERVERROOT . '/data/' + ); + $this->oldAllowedBackends = OCP\Config::getAppValue( + 'files_external', + 'user_mounting_backends', + '' + ); + $this->allBackends = OC_Mount_Config::getBackends(); + OCP\Config::setAppValue( + 'files_external', + 'user_mounting_backends', + implode(',', array_keys($this->allBackends)) + ); + + OC_Mount_Config::$skipTest = true; + } + + public function tearDown() { + OC_Mount_Config::$skipTest = false; + + \OC_User::deleteUser(self::TEST_USER2); + \OC_User::deleteUser(self::TEST_USER1); + \OC_Group::deleteGroup(self::TEST_GROUP1); + \OC_Group::deleteGroup(self::TEST_GROUP2); + + @unlink($this->dataDir . '/mount.json'); + + OCP\Config::setAppValue( + 'files_external', + 'user_mounting_backends', + $this->oldAllowedBackends + ); + } + + /** + * Reads the global config, for checking + */ + private function readGlobalConfig() { + $configFile = $this->dataDir . '/mount.json'; + return json_decode(file_get_contents($configFile), true); + } + + /** + * Reads the user config, for checking + */ + private function readUserConfig() { + $configFile = $this->userHome . '/mount.json'; + return json_decode(file_get_contents($configFile), true); + } + + /** + * Write the user config, to simulate existing files + */ + private function writeUserConfig($config) { + $configFile = $this->userHome . '/mount.json'; + file_put_contents($configFile, json_encode($config)); + } + /** * Test mount point validation */ @@ -42,10 +124,515 @@ class Test_Mount_Config extends \PHPUnit_Framework_TestCase { $mountType = 'user'; $applicable = 'all'; $isPersonal = false; - $this->assertEquals(false, OC_Mount_Config::addMountPoint('', $storageClass, array(), $mountType, $applicable, $isPersonal)); - $this->assertEquals(false, OC_Mount_Config::addMountPoint('/', $storageClass, array(), $mountType, $applicable, $isPersonal)); - $this->assertEquals(false, OC_Mount_Config::addMountPoint('Shared', $storageClass, array(), $mountType, $applicable, $isPersonal)); - $this->assertEquals(false, OC_Mount_Config::addMountPoint('/Shared', $storageClass, array(), $mountType, $applicable, $isPersonal)); + $this->assertFalse(OC_Mount_Config::addMountPoint('', $storageClass, array(), $mountType, $applicable, $isPersonal)); + $this->assertFalse(OC_Mount_Config::addMountPoint('/', $storageClass, array(), $mountType, $applicable, $isPersonal)); + } + + /** + * Test adding a global mount point + */ + public function testAddGlobalMountPoint() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = 'all'; + $isPersonal = false; + + $this->assertEquals(true, OC_Mount_Config::addMountPoint('/ext', '\OC\Files\Storage\SFTP', array(), $mountType, $applicable, $isPersonal)); + + $config = $this->readGlobalConfig(); + $this->assertEquals(1, count($config)); + $this->assertTrue(isset($config[$mountType])); + $this->assertTrue(isset($config[$mountType][$applicable])); + $this->assertTrue(isset($config[$mountType][$applicable]['/$user/files/ext'])); + $this->assertEquals( + '\OC\Files\Storage\SFTP', + $config[$mountType][$applicable]['/$user/files/ext']['class'] + ); + } + + /** + * Test adding a personal mount point + */ + public function testAddMountPointSingleUser() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = self::TEST_USER1; + $isPersonal = true; + + $this->assertEquals(true, OC_Mount_Config::addMountPoint('/ext', '\OC\Files\Storage\SFTP', array(), $mountType, $applicable, $isPersonal)); + + $config = $this->readUserConfig(); + $this->assertEquals(1, count($config)); + $this->assertTrue(isset($config[$mountType])); + $this->assertTrue(isset($config[$mountType][$applicable])); + $this->assertTrue(isset($config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext'])); + $this->assertEquals( + '\OC\Files\Storage\SFTP', + $config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']['class'] + ); + } + + /** + * Test adding a personal mount point using disallowed backend + */ + public function testAddDisallowedBackendMountPointSingleUser() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = self::TEST_USER1; + $isPersonal = true; + + // local + $this->assertFalse(OC_Mount_Config::addMountPoint('/ext', '\OC\Files\storage\local', array(), $mountType, $applicable, $isPersonal)); + + unset($this->allBackends['\OC\Files\Storage\SFTP']); + OCP\Config::setAppValue( + 'files_external', + 'user_mounting_backends', + implode(',', array_keys($this->allBackends)) + ); + + // non-local but forbidden + $this->assertFalse(OC_Mount_Config::addMountPoint('/ext', '\OC\Files\Storage\SFTP', array(), $mountType, $applicable, $isPersonal)); + + $this->assertFalse(file_exists($this->userHome . '/mount.json')); + } + + /** + * Test adding a mount point with an non-existant backend + */ + public function testAddMountPointUnexistClass() { + $storageClass = 'Unexist_Storage'; + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = self::TEST_USER1; + $isPersonal = false; + $this->assertFalse(OC_Mount_Config::addMountPoint('/ext', $storageClass, array(), $mountType, $applicable, $isPersonal)); } + + /** + * 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, $applicable, $expectApplicableArray) { + $mountType = $mountType; + $applicable = $applicable; + $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, + $mountType, + $applicable, + $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($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($options), array_keys($savedOptions)); + } + + /** + * Test reading and writing config + */ + public function testReadWritePersonalConfig() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = self::TEST_USER1; + $isPersonal = true; + $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, + $mountType, + $applicable, + $isPersonal + ) + ); + + // re-read config + $config = OC_Mount_Config::getPersonalMountPoints(); + $this->assertEquals(1, count($config)); + $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($options), array_keys($savedOptions)); + } + + /** + * Test password obfuscation + */ + public function testPasswordObfuscation() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = self::TEST_USER1; + $isPersonal = true; + $mountConfig = array( + 'host' => 'smbhost', + 'user' => 'smbuser', + 'password' => 'smbpassword', + 'share' => 'smbshare', + 'root' => 'smbroot' + ); + + // write config + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $mountConfig, + $mountType, + $applicable, + $isPersonal + ) + ); + + // note: password re-reading is covered by testReadWritePersonalConfig + + // check that password inside the file is NOT in plain text + $config = $this->readUserConfig(); + $savedConfig = $config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']['options']; + + // no more clear text password in file (kept because of key order) + $this->assertEquals('', $savedConfig['password']); + + // encrypted password is present + $this->assertNotEquals($mountConfig['password'], $savedConfig['password_encrypted']); + } + + /** + * Test read legacy passwords + */ + public function testReadLegacyPassword() { + $mountType = OC_Mount_Config::MOUNT_TYPE_USER; + $applicable = self::TEST_USER1; + $isPersonal = true; + $mountConfig = array( + 'host' => 'smbhost', + 'user' => 'smbuser', + 'password' => 'smbpassword', + 'share' => 'smbshare', + 'root' => 'smbroot' + ); + + // write config + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $mountConfig, + $mountType, + $applicable, + $isPersonal + ) + ); + + $config = $this->readUserConfig(); + // simulate non-encrypted password situation + $config[$mountType][$applicable]['/' . self::TEST_USER1 . '/files/ext']['options']['password'] = 'smbpasswd'; + + $this->writeUserConfig($config); + + // re-read config, password was read correctly + $config = OC_Mount_Config::getPersonalMountPoints(); + $savedMountConfig = $config[0]['options']; + $this->assertEquals($mountConfig, $savedMountConfig); + } + + public function mountDataProvider() { + return array( + // Tests for visible mount points + // system mount point for all users + array( + false, + OC_Mount_Config::MOUNT_TYPE_USER, + 'all', + self::TEST_USER1, + true, + ), + // system mount point for a specific user + array( + false, + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER1, + self::TEST_USER1, + true, + ), + // system mount point for a specific group + array( + false, + OC_Mount_Config::MOUNT_TYPE_GROUP, + self::TEST_GROUP1, + self::TEST_USER1, + true, + ), + // user mount point + array( + true, + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER1, + self::TEST_USER1, + true, + ), + + // Tests for non-visible mount points + // system mount point for another user + array( + false, + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER2, + self::TEST_USER1, + false, + ), + // system mount point for a specific group + array( + false, + OC_Mount_Config::MOUNT_TYPE_GROUP, + self::TEST_GROUP2, + self::TEST_USER1, + false, + ), + // user mount point + array( + true, + OC_Mount_Config::MOUNT_TYPE_USER, + self::TEST_USER1, + self::TEST_USER2, + false, + ), + ); + } + + /** + * Test mount points used at mount time, making sure + * the configuration is prepared properly. + * + * @dataProvider mountDataProvider + * @param bool $isPersonal true for personal mount point, false for system mount point + * @param string $mountType mount type + * @param string $applicable target user/group or "all" + * @param string $testUser user for which to retrieve the mount points + * @param bool $expectVisible whether to expect the mount point to be visible for $testUser + */ + public function testMount($isPersonal, $mountType, $applicable, $testUser, $expectVisible) { + $mountConfig = array( + 'host' => 'someost', + 'user' => 'someuser', + 'password' => 'somepassword', + 'root' => 'someroot' + ); + + // add mount point as "test" user + $this->assertTrue( + OC_Mount_Config::addMountPoint( + '/ext', + '\OC\Files\Storage\SMB', + $mountConfig, + $mountType, + $applicable, + $isPersonal + ) + ); + + // check mount points in the perspective of user $testUser + \OC_User::setUserId($testUser); + + $mountPoints = OC_Mount_Config::getAbsoluteMountPoints($testUser); + if ($expectVisible) { + $this->assertEquals(1, count($mountPoints)); + $this->assertTrue(isset($mountPoints['/' . self::TEST_USER1 . '/files/ext'])); + $this->assertEquals('\OC\Files\Storage\SMB', $mountPoints['/' . self::TEST_USER1 . '/files/ext']['class']); + $this->assertEquals($mountConfig, $mountPoints['/' . self::TEST_USER1 . '/files/ext']['options']); + } + else { + $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 0000000000..4b64549625 --- /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/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php index d12d212a2e..d8c892f1b7 100644 --- a/apps/files_sharing/ajax/publicpreview.php +++ b/apps/files_sharing/ajax/publicpreview.php @@ -16,6 +16,7 @@ $maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '36'; $maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '36'; $scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true; $token = array_key_exists('t', $_GET) ? (string) $_GET['t'] : ''; +$keepAspect = array_key_exists('a', $_GET) ? true : false; if($token === ''){ \OC_Response::setStatus(400); //400 Bad Request @@ -70,6 +71,10 @@ if(substr($path, 0, 1) === '/') { $path = substr($path, 1); } +if ($keepAspect === true) { + $maxY = $maxX; +} + if($maxX === 0 || $maxY === 0) { \OC_Response::setStatus(400); //400 Bad Request \OC_Log::write('core-preview', 'x and/or y set to 0', \OC_Log::DEBUG); @@ -84,8 +89,9 @@ try{ $preview->setMaxX($maxX); $preview->setMaxY($maxY); $preview->setScalingUp($scalingUp); + $preview->setKeepAspect($keepAspect); - $preview->show(); + $preview->showPreview(); } catch (\Exception $e) { \OC_Response::setStatus(500); \OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG); diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 217bc005fa..0ef3457811 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -17,6 +17,4 @@ OCP\Util::addScript('files_sharing', 'share'); \OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Shared_Updater', 'postDeleteHook'); \OC_Hook::connect('OC_Filesystem', 'delete', '\OC\Files\Cache\Shared_Updater', 'deleteHook'); \OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Shared_Updater', 'renameHook'); -\OC_Hook::connect('OCP\Share', 'post_shared', '\OC\Files\Cache\Shared_Updater', 'shareHook'); -\OC_Hook::connect('OCP\Share', 'pre_unshare', '\OC\Files\Cache\Shared_Updater', 'shareHook'); \OC_Hook::connect('OC_Appconfig', 'post_set_value', '\OCA\Files\Share\Maintainer', 'configChangeHook'); diff --git a/apps/files_sharing/appinfo/info.xml b/apps/files_sharing/appinfo/info.xml index 9a199281a7..9b42c1e17b 100644 --- a/apps/files_sharing/appinfo/info.xml +++ b/apps/files_sharing/appinfo/info.xml @@ -13,6 +13,6 @@ public.php - public.php + publicwebdav.php diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index 3469829b6f..7c2834dc9c 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -1,8 +1,9 @@ create('core_ajax_public_preview', '/publicpreview.png')->action( -function() { - require_once __DIR__ . '/../ajax/publicpreview.php'; -}); +/** @var $this \OCP\Route\IRouter */ +$this->create('core_ajax_public_preview', '/publicpreview')->action( + function() { + require_once __DIR__ . '/../ajax/publicpreview.php'; + }); // OCS API diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 4b716e764f..bc8cda4231 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -1,89 +1,77 @@ execute(); - $groupShares = array(); - //we need to set up user backends, otherwise creating the shares will fail with "because user does not exist" - OC_User::useBackend(new OC_User_Database()); - OC_Group::useBackend(new OC_Group_Database()); - OC_App::loadApps(array('authentication')); - $rootView = new \OC\Files\View(''); - while ($row = $result->fetchRow()) { - $meta = $rootView->getFileInfo($$row['source']); - $itemSource = $meta['fileid']; - if ($itemSource != -1) { - $file = $meta; - if ($file['mimetype'] == 'httpd/unix-directory') { - $itemType = 'folder'; - } else { - $itemType = 'file'; - } - if ($row['permissions'] == 0) { - $permissions = OCP\PERMISSION_READ | OCP\PERMISSION_SHARE; - } else { - $permissions = OCP\PERMISSION_READ | OCP\PERMISSION_UPDATE | OCP\PERMISSION_SHARE; - if ($itemType == 'folder') { - $permissions |= OCP\PERMISSION_CREATE; - } - } - $pos = strrpos($row['uid_shared_with'], '@'); - if ($pos !== false && OC_Group::groupExists(substr($row['uid_shared_with'], $pos + 1))) { - $shareType = OCP\Share::SHARE_TYPE_GROUP; - $shareWith = substr($row['uid_shared_with'], 0, $pos); - if (isset($groupShares[$shareWith][$itemSource])) { - continue; - } else { - $groupShares[$shareWith][$itemSource] = true; - } - } else if ($row['uid_shared_with'] == 'public') { - $shareType = OCP\Share::SHARE_TYPE_LINK; - $shareWith = null; - } else { - $shareType = OCP\Share::SHARE_TYPE_USER; - $shareWith = $row['uid_shared_with']; - } - OCP\JSON::checkUserExists($row['uid_owner']); - OC_User::setUserId($row['uid_owner']); - //we need to setup the filesystem for the user, otherwise OC_FileSystem::getRoot will fail and break - OC_Util::setupFS($row['uid_owner']); - try { - OCP\Share::shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions); - } - catch (Exception $e) { - $update_error = true; - OCP\Util::writeLog('files_sharing', - 'Upgrade Routine: Skipping sharing "'.$row['source'].'" to "'.$shareWith - .'" (error is "'.$e->getMessage().'")', - OCP\Util::WARN); - } - OC_Util::tearDownFS(); - } - } - OC_User::setUserId(null); - if ($update_error) { - OCP\Util::writeLog('files_sharing', 'There were some problems upgrading the sharing of files', OCP\Util::ERROR); - } - // NOTE: Let's drop the table after more testing -// $query = OCP\DB::prepare('DROP TABLE `*PREFIX*sharing`'); -// $query->execute(); +if (version_compare($installedVersion, '0.4', '<')) { + removeSharedFolder(); } // clean up oc_share table from files which are no longer exists -if (version_compare($installedVersion, '0.3.5', '<')) { +if (version_compare($installedVersion, '0.3.5.6', '<')) { + \OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate(); +} - // 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']; +/** + * update script for the removal of the logical "Shared" folder, we create physical "Shared" folder and + * update the users file_target so that it doesn't make any difference for the user + * @note parameters are just for testing, please ignore them + */ +function removeSharedFolder($mkdirs = true, $chunkSize = 99) { + $query = OCP\DB::prepare('SELECT * FROM `*PREFIX*share`'); + $result = $query->execute(); + $view = new \OC\Files\View('/'); + $users = array(); + $shares = array(); + //we need to set up user backends + OC_User::useBackend(new OC_User_Database()); + OC_Group::useBackend(new OC_Group_Database()); + OC_App::loadApps(array('authentication')); + //we need to set up user backends, otherwise creating the shares will fail with "because user does not exist" + while ($row = $result->fetchRow()) { + //collect all user shares + if ((int)$row['share_type'] === 0 && ($row['item_type'] === 'file' || $row['item_type'] === 'folder')) { + $users[] = $row['share_with']; + $shares[$row['id']] = $row['file_target']; + } else if ((int)$row['share_type'] === 1 && ($row['item_type'] === 'file' || $row['item_type'] === 'folder')) { + //collect all group shares + $users = array_merge($users, \OC_group::usersInGroup($row['share_with'])); + $shares[$row['id']] = $row['file_target']; + } else if ((int)$row['share_type'] === 2) { + $shares[$row['id']] = $row['file_target']; } - $removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `file_source` IN (?)'); - $result = $removeShares->execute(array(implode(',', $delArray))); + } + + $unique_users = array_unique($users); + + if (!empty($unique_users) && !empty($shares)) { + + // create folder Shared for each user + + if ($mkdirs) { + foreach ($unique_users as $user) { + \OC\Files\Filesystem::initMountPoints($user); + if (!$view->file_exists('/' . $user . '/files/Shared')) { + $view->mkdir('/' . $user . '/files/Shared'); + } + } + } + + $chunkedShareList = array_chunk($shares, $chunkSize, true); + + foreach ($chunkedShareList as $subList) { + + $statement = "UPDATE `*PREFIX*share` SET `file_target` = CASE `id` "; + //update share table + $ids = implode(',', array_keys($subList)); + foreach ($subList as $id => $target) { + $statement .= "WHEN " . $id . " THEN '/Shared" . $target . "' "; + } + $statement .= ' END WHERE `id` IN (' . $ids . ')'; + + $query = OCP\DB::prepare($statement); + + $query->execute(array()); + } + } } diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version index 09e9157034..267577d47e 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.4.1 diff --git a/apps/files_sharing/css/mobile.css b/apps/files_sharing/css/mobile.css index 7d2116d190..333c4c77fc 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 5246a4b2fe..67d8470194 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -1,32 +1,3 @@ -body { - height: auto; -} - -#header { - background-color: #1d2d44; - height:32px; - left:0; - line-height:32px; - position:fixed; - right:0; - top:0; - z-index:100; - padding:7px; -} - -.header-right { - padding: 0; - height: 32px; -} - -#details { - color:#fff; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; - filter: alpha(opacity=50); - opacity: .5; - padding-right: 5px; -} - #controls { left: 0; } @@ -35,6 +6,11 @@ body { background: #fff; text-align: center; margin: 45px auto 0; + min-height: 150px; +} + +#preview .notCreatable { + display: none; } #noPreview { @@ -94,13 +70,23 @@ thead { margin: 0; } + .directDownload, .directLink { margin-bottom: 20px; } -.directDownload .button img { - vertical-align: text-bottom; + +/* keep long file names in one line to not overflow download button on mobile */ +.directDownload #download { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 90%; + display: inline-block; + margin-left: auto; + margin-right: auto; } + .directLink label { font-weight: normal; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; @@ -110,4 +96,5 @@ thead { .directLink input { margin-left: 5px; width: 300px; + max-width: 90%; } diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 06c168969d..0b4dec8176 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -8,38 +8,41 @@ * */ -/* 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() { + var mimetype = $('#mimetype').val(); + if (typeof FileActions !== 'undefined') { - var mimetype = $('#mimetype').val(); // Show file preview if previewer is available, images are already handled by the template - if (mimetype.substr(0, mimetype.indexOf('/')) != 'image' && $('.publicpreview').length === 0) { + if (mimetype.substr(0, mimetype.indexOf('/')) !== 'image' && $('.publicpreview').length === 0) { // Trigger default action if not download TODO var action = FileActions.getDefault(mimetype, 'file', OC.PERMISSION_READ); if (typeof action !== 'undefined') { 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) { + // dynamically load image previews + if (mimetype.substr(0, mimetype.indexOf('/')) === 'image' ) { + + var params = { + x: $(document).width() * window.devicePixelRatio, + a: 'true', + file: encodeURIComponent($('#dir').val() + $('#filename').val()), + t: $('#sharingToken').val() + }; + + var img = $(''); + img.attr('src', OC.filePath('files_sharing', 'ajax', 'publicpreview.php') + '?' + OC.buildQueryString(params)); + img.appendTo('#imgframe'); + } + + // override since the format is different + if (typeof Files !== 'undefined') { + Files.getDownloadUrl = function(filename, dir) { if ($.isArray(filename)) { filename = JSON.stringify(filename); } @@ -48,24 +51,48 @@ $(document).ready(function() { service: 'files', t: $('#sharingToken').val(), path: path, + files: filename, download: null }; - if (filename) { - params.files = filename; - } return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); }; - } - var file_upload_start = $('#file_upload_start'); - file_upload_start.on('fileuploadadd', function(e, data) { - // Add custom data to the upload handler - data.formData = { - requesttoken: $('#publicUploadRequestToken').val(), - dirToken: $('#dirToken').val(), - subdir: $('input#dir').val() + 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) { + var fileDirectory = ''; + if(typeof data.files[0].relativePath !== 'undefined') { + fileDirectory = data.files[0].relativePath; + } + + // Add custom data to the upload handler + data.formData = { + requesttoken: $('#publicUploadRequestToken').val(), + dirToken: $('#dirToken').val(), + subdir: $('input#dir').val(), + file_directory: fileDirectory + }; + }); + } $(document).on('click', '#directLink', function() { $(this).focus(); diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 36de452a55..3c7c9239a6 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -1,10 +1,38 @@ +/* + * 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] [data-Action="Share"]'); + allShared.addClass('permanent'); + allShared.find('span').text(function(){ + var $owner = $(this).closest('tr').attr('data-share-owner'); + return ' ' + t('files_sharing', 'Shared by {owner}', {owner: $owner}); + }); + if (!sharesLoaded){ OC.Share.loadIcons('file'); // assume that we got all shares, so switching directories @@ -17,16 +45,10 @@ $(document).ready(function() { }); FileActions.register('all', 'Share', OC.PERMISSION_READ, OC.imagePath('core', 'actions/share'), function(filename) { - if ($('#dir').val() == '/') { - var item = $('#dir').val() + filename; - } else { - var item = $('#dir').val() + '/' + filename; - } var tr = FileList.findFileEl(filename); + var itemType = 'file'; if ($(tr).data('type') == 'dir') { - var itemType = 'folder'; - } else { - var itemType = 'file'; + itemType = 'folder'; } var possiblePermissions = $(tr).data('permissions'); var appendTo = $(tr).find('td.filename'); diff --git a/apps/files_sharing/l10n/ar.php b/apps/files_sharing/l10n/ar.php index 2625af1cc0..3f8b49913f 100644 --- a/apps/files_sharing/l10n/ar.php +++ b/apps/files_sharing/l10n/ar.php @@ -1,11 +1,17 @@ "مشاركة من طرف {owner}", +"This share is password-protected" => "هذه المشاركة محمية بكلمة مرور", +"The password is wrong. Try again." => "كلمة المرور خاطئة. حاول مرة أخرى", "Password" => "كلمة المرور", -"%s shared the folder %s with you" => "%s شارك المجلد %s معك", -"%s shared the file %s with you" => "%s شارك الملف %s معك", +"Sorry, this link doesn’t seem to work anymore." => "عذرا، يبدو أن هذا الرابط لم يعد يعمل.", +"Reasons might be:" => "الأسباب الممكنة :", +"the item was removed" => "تم حذف العنصر المطلوب", +"the link expired" => "انتهت صلاحية الرابط", +"sharing is disabled" => "المشاركة غير مفعلة", +"For more info, please ask the person who sent this link." => "لمزيد من المعلومات، يرجى سؤال الشخص الذي أرسل هذا الرابط", "Download" => "تحميل", -"Upload" => "رفع", -"Cancel upload" => "إلغاء رفع الملفات", -"No preview available for" => "لا يوجد عرض مسبق لـ" +"Download %s" => "تحميل %s", +"Direct link" => "رابط مباشر" ); $PLURAL_FORMS = "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"; diff --git a/apps/files_sharing/l10n/ast.php b/apps/files_sharing/l10n/ast.php new file mode 100644 index 0000000000..d90df88723 --- /dev/null +++ b/apps/files_sharing/l10n/ast.php @@ -0,0 +1,7 @@ + "Compartíu por {owner}", +"Password" => "Contraseña", +"Download" => "Baxar" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/bg_BG.php b/apps/files_sharing/l10n/bg_BG.php index f4b9e2dd5f..80bc117687 100644 --- a/apps/files_sharing/l10n/bg_BG.php +++ b/apps/files_sharing/l10n/bg_BG.php @@ -1,11 +1,6 @@ "Парола", -"%s shared the folder %s with you" => "%s сподели папката %s с Вас", -"%s shared the file %s with you" => "%s сподели файла %s с Вас", -"Download" => "Изтегляне", -"Upload" => "Качване", -"Cancel upload" => "Спри качването", -"No preview available for" => "Няма наличен преглед за" +"Download" => "Изтегляне" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/bn_BD.php b/apps/files_sharing/l10n/bn_BD.php index aaed904d9d..6c5809f5a0 100644 --- a/apps/files_sharing/l10n/bn_BD.php +++ b/apps/files_sharing/l10n/bn_BD.php @@ -1,11 +1,6 @@ "কূটশব্দ", -"%s shared the folder %s with you" => "%s আপনার সাথে %s ফোল্ডারটি ভাগাভাগি করেছেন", -"%s shared the file %s with you" => "%s আপনার সাথে %s ফাইলটি ভাগাভাগি করেছেন", -"Download" => "ডাউনলোড", -"Upload" => "আপলোড", -"Cancel upload" => "আপলোড বাতিল কর", -"No preview available for" => "এর জন্য কোন প্রাকবীক্ষণ সুলভ নয়" +"Download" => "ডাউনলোড" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/ca.php b/apps/files_sharing/l10n/ca.php index 96e5999296..8b23af6964 100644 --- a/apps/files_sharing/l10n/ca.php +++ b/apps/files_sharing/l10n/ca.php @@ -1,5 +1,6 @@ "Compartits per {owner}", "This share is password-protected" => "Aquest compartit està protegit amb contrasenya", "The password is wrong. Try again." => "la contrasenya és incorrecta. Intenteu-ho de nou.", "Password" => "Contrasenya", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "l'enllaç ha vençut", "sharing is disabled" => "s'ha desactivat la compartició", "For more info, please ask the person who sent this link." => "Per més informació contacteu amb qui us ha enviat l'enllaç.", -"%s shared the folder %s with you" => "%s ha compartit la carpeta %s amb vós", -"%s shared the file %s with you" => "%s ha compartit el fitxer %s amb vós", "Download" => "Baixa", -"Upload" => "Puja", -"Cancel upload" => "Cancel·la la pujada", -"No preview available for" => "No hi ha vista prèvia disponible per a", +"Download %s" => "Baixa %s", "Direct link" => "Enllaç directe" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/cs_CZ.php b/apps/files_sharing/l10n/cs_CZ.php index adf099a6d9..d77cc79494 100644 --- a/apps/files_sharing/l10n/cs_CZ.php +++ b/apps/files_sharing/l10n/cs_CZ.php @@ -1,5 +1,6 @@ "Sdílí {owner}", "This share is password-protected" => "Toto sdílení je chráněno heslem", "The password is wrong. Try again." => "Heslo není správné. Zkuste to znovu.", "Password" => "Heslo", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "platnost odkazu vypršela", "sharing is disabled" => "sdílení je zakázané", "For more info, please ask the person who sent this link." => "Pro více informací kontaktujte osobu, která vám zaslala tento odkaz.", -"%s shared the folder %s with you" => "%s s Vámi sdílí složku %s", -"%s shared the file %s with you" => "%s s Vámi sdílí soubor %s", "Download" => "Stáhnout", -"Upload" => "Odeslat", -"Cancel upload" => "Zrušit odesílání", -"No preview available for" => "Náhled není dostupný pro", +"Download %s" => "Stáhnout %s", "Direct link" => "Přímý odkaz" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/apps/files_sharing/l10n/cy_GB.php b/apps/files_sharing/l10n/cy_GB.php index d2ae28141d..0012a9fa7f 100644 --- a/apps/files_sharing/l10n/cy_GB.php +++ b/apps/files_sharing/l10n/cy_GB.php @@ -1,11 +1,6 @@ "Cyfrinair", -"%s shared the folder %s with you" => "Rhannodd %s blygell %s â chi", -"%s shared the file %s with you" => "Rhannodd %s ffeil %s â chi", -"Download" => "Llwytho i lawr", -"Upload" => "Llwytho i fyny", -"Cancel upload" => "Diddymu llwytho i fyny", -"No preview available for" => "Does dim rhagolwg ar gael ar gyfer" +"Download" => "Llwytho i lawr" ); $PLURAL_FORMS = "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"; diff --git a/apps/files_sharing/l10n/da.php b/apps/files_sharing/l10n/da.php index 849b0e28d3..07fc5392a8 100644 --- a/apps/files_sharing/l10n/da.php +++ b/apps/files_sharing/l10n/da.php @@ -1,5 +1,6 @@ "Delt af {owner}", "This share is password-protected" => "Delingen er beskyttet af kodeord", "The password is wrong. Try again." => "Kodeordet er forkert. Prøv igen.", "Password" => "Kodeord", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "linket udløb", "sharing is disabled" => "deling er deaktiveret", "For more info, please ask the person who sent this link." => "For yderligere information, kontakt venligst personen der sendte linket. ", -"%s shared the folder %s with you" => "%s delte mappen %s med dig", -"%s shared the file %s with you" => "%s delte filen %s med dig", "Download" => "Download", -"Upload" => "Upload", -"Cancel upload" => "Fortryd upload", -"No preview available for" => "Forhåndsvisning ikke tilgængelig for", +"Download %s" => "Download %s", "Direct link" => "Direkte link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/de.php b/apps/files_sharing/l10n/de.php index d7879833ca..2ca1a006a9 100644 --- a/apps/files_sharing/l10n/de.php +++ b/apps/files_sharing/l10n/de.php @@ -1,5 +1,6 @@ "Geteilt von {owner}", "This share is password-protected" => "Diese Freigabe ist durch ein Passwort geschützt", "The password is wrong. Try again." => "Bitte überprüfe Dein Passwort und versuche es erneut.", "Password" => "Passwort", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "Der Link ist abgelaufen", "sharing is disabled" => "Teilen ist deaktiviert", "For more info, please ask the person who sent this link." => "Für mehr Informationen, frage bitte die Person, die Dir diesen Link geschickt hat.", -"%s shared the folder %s with you" => "%s hat den Ordner %s mit Dir geteilt", -"%s shared the file %s with you" => "%s hat die Datei %s mit Dir geteilt", -"Download" => "Download", -"Upload" => "Upload", -"Cancel upload" => "Upload abbrechen", -"No preview available for" => "Es ist keine Vorschau verfügbar für", +"Download" => "Herunterladen", +"Download %s" => "Download %s", "Direct link" => "Direkter Link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/de_AT.php b/apps/files_sharing/l10n/de_AT.php new file mode 100644 index 0000000000..08ef4d9245 --- /dev/null +++ b/apps/files_sharing/l10n/de_AT.php @@ -0,0 +1,6 @@ + "Passwort", +"Download" => "Herunterladen" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/de_CH.php b/apps/files_sharing/l10n/de_CH.php index f63714b902..8d3c5f6ed7 100644 --- a/apps/files_sharing/l10n/de_CH.php +++ b/apps/files_sharing/l10n/de_CH.php @@ -1,5 +1,6 @@ "Geteilt von {owner}", "The password is wrong. Try again." => "Das Passwort ist falsch. Bitte versuchen Sie es erneut.", "Password" => "Passwort", "Sorry, this link doesn’t seem to work anymore." => "Entschuldigung, dieser Link scheint nicht mehr zu funktionieren.", @@ -8,11 +9,6 @@ $TRANSLATIONS = array( "the link expired" => "Der Link ist abgelaufen", "sharing is disabled" => "Teilen ist deaktiviert", "For more info, please ask the person who sent this link." => "Für mehr Informationen, fragen Sie bitte die Person, die Ihnen diesen Link geschickt hat.", -"%s shared the folder %s with you" => "%s hat den Ordner %s mit Ihnen geteilt", -"%s shared the file %s with you" => "%s hat die Datei %s mit Ihnen geteilt", -"Download" => "Herunterladen", -"Upload" => "Hochladen", -"Cancel upload" => "Upload abbrechen", -"No preview available for" => "Es ist keine Vorschau verfügbar für" +"Download" => "Herunterladen" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/de_DE.php b/apps/files_sharing/l10n/de_DE.php index 3ab95b6690..021ec041aa 100644 --- a/apps/files_sharing/l10n/de_DE.php +++ b/apps/files_sharing/l10n/de_DE.php @@ -1,5 +1,6 @@ "Geteilt von {owner}", "This share is password-protected" => "Diese Freigabe ist durch ein Passwort geschützt", "The password is wrong. Try again." => "Das Passwort ist falsch. Bitte versuchen Sie es erneut.", "Password" => "Passwort", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "Der Link ist abgelaufen", "sharing is disabled" => "Teilen ist deaktiviert", "For more info, please ask the person who sent this link." => "Für mehr Informationen, fragen Sie bitte die Person, die Ihnen diesen Link geschickt hat.", -"%s shared the folder %s with you" => "%s hat den Ordner %s mit Ihnen geteilt", -"%s shared the file %s with you" => "%s hat die Datei %s mit Ihnen geteilt", "Download" => "Herunterladen", -"Upload" => "Hochladen", -"Cancel upload" => "Upload abbrechen", -"No preview available for" => "Es ist keine Vorschau verfügbar für", +"Download %s" => "Download %s", "Direct link" => "Direkte Verlinkung" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/el.php b/apps/files_sharing/l10n/el.php index 3ea666504b..eb559a682d 100644 --- a/apps/files_sharing/l10n/el.php +++ b/apps/files_sharing/l10n/el.php @@ -1,5 +1,6 @@ "Διαμοιράστηκε από τον {owner}", "This share is password-protected" => "Αυτός ο κοινόχρηστος φάκελος προστατεύεται με κωδικό", "The password is wrong. Try again." => "Εσφαλμένος κωδικός πρόσβασης. Προσπαθήστε ξανά.", "Password" => "Κωδικός πρόσβασης", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "ο σύνδεσμος έληξε", "sharing is disabled" => "ο διαμοιρασμός απενεργοποιήθηκε", "For more info, please ask the person who sent this link." => "Για περισσότερες πληροφορίες, παρακαλώ ρωτήστε το άτομο που σας έστειλε αυτόν τον σύνδεσμο.", -"%s shared the folder %s with you" => "Ο %s μοιράστηκε τον φάκελο %s μαζί σας", -"%s shared the file %s with you" => "Ο %s μοιράστηκε το αρχείο %s μαζί σας", "Download" => "Λήψη", -"Upload" => "Μεταφόρτωση", -"Cancel upload" => "Ακύρωση μεταφόρτωσης", -"No preview available for" => "Δεν υπάρχει διαθέσιμη προεπισκόπηση για", +"Download %s" => "Λήψη %s", "Direct link" => "Άμεσος σύνδεσμος" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/en@pirate.php b/apps/files_sharing/l10n/en@pirate.php index cd3c00d29d..a927110900 100644 --- a/apps/files_sharing/l10n/en@pirate.php +++ b/apps/files_sharing/l10n/en@pirate.php @@ -1,9 +1,6 @@ "Secret Code", -"%s shared the folder %s with you" => "%s shared the folder %s with you", -"%s shared the file %s with you" => "%s shared the file %s with you", -"Download" => "Download", -"No preview available for" => "No preview available for" +"Download" => "Download" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/en_GB.php b/apps/files_sharing/l10n/en_GB.php index 3e04d120be..e263f3cf6d 100644 --- a/apps/files_sharing/l10n/en_GB.php +++ b/apps/files_sharing/l10n/en_GB.php @@ -1,5 +1,6 @@ "Shared by {owner}", "This share is password-protected" => "This share is password-protected", "The password is wrong. Try again." => "The password is wrong. Try again.", "Password" => "Password", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "the link expired", "sharing is disabled" => "sharing is disabled", "For more info, please ask the person who sent this link." => "For more info, please ask the person who sent this link.", -"%s shared the folder %s with you" => "%s shared the folder %s with you", -"%s shared the file %s with you" => "%s shared the file %s with you", "Download" => "Download", -"Upload" => "Upload", -"Cancel upload" => "Cancel upload", -"No preview available for" => "No preview available for", +"Download %s" => "Download %s", "Direct link" => "Direct link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/eo.php b/apps/files_sharing/l10n/eo.php index 891b3db9aa..127ac02206 100644 --- a/apps/files_sharing/l10n/eo.php +++ b/apps/files_sharing/l10n/eo.php @@ -1,5 +1,6 @@ "Kunhavigita de {owner}", "This share is password-protected" => "Ĉi tiu kunhavigo estas protektata per pasvorto", "Password" => "Pasvorto", "Sorry, this link doesn’t seem to work anymore." => "Pardonu, ĉi tiu ligilo ŝajne ne plu funkcias.", @@ -8,12 +9,7 @@ $TRANSLATIONS = array( "the link expired" => "la ligilo eksvalidiĝis", "sharing is disabled" => "kunhavigo malkapablas", "For more info, please ask the person who sent this link." => "Por plia informo, bonvolu peti al la persono, kiu sendis ĉi tiun ligilon.", -"%s shared the folder %s with you" => "%s kunhavigis la dosierujon %s kun vi", -"%s shared the file %s with you" => "%s kunhavigis la dosieron %s kun vi", "Download" => "Elŝuti", -"Upload" => "Alŝuti", -"Cancel upload" => "Nuligi alŝuton", -"No preview available for" => "Ne haveblas antaŭvido por", "Direct link" => "Direkta ligilo" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/es.php b/apps/files_sharing/l10n/es.php index f986c29b4f..6978c7ce72 100644 --- a/apps/files_sharing/l10n/es.php +++ b/apps/files_sharing/l10n/es.php @@ -1,5 +1,6 @@ "Compartido por {owner}", "This share is password-protected" => "Este elemento compartido esta protegido por contraseña", "The password is wrong. Try again." => "La contraseña introducida es errónea. Inténtelo de nuevo.", "Password" => "Contraseña", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "el enlace expiró", "sharing is disabled" => "compartir está desactivado", "For more info, please ask the person who sent this link." => "Para mayor información, contacte a la persona que le envió el enlace.", -"%s shared the folder %s with you" => "%s compartió la carpeta %s contigo", -"%s shared the file %s with you" => "%s compartió el fichero %s contigo", "Download" => "Descargar", -"Upload" => "Subir", -"Cancel upload" => "Cancelar subida", -"No preview available for" => "No hay vista previa disponible para", +"Download %s" => "Descargar %s", "Direct link" => "Enlace directo" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/es_AR.php b/apps/files_sharing/l10n/es_AR.php index 989a91a450..9a9db79493 100644 --- a/apps/files_sharing/l10n/es_AR.php +++ b/apps/files_sharing/l10n/es_AR.php @@ -1,5 +1,7 @@ "Compartido por {owner}", +"This share is password-protected" => "Esto está protegido por contraseña", "The password is wrong. Try again." => "La contraseña no es correcta. Probá de nuevo.", "Password" => "Contraseña", "Sorry, this link doesn’t seem to work anymore." => "Perdón, este enlace parece no funcionar más.", @@ -8,11 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "el enlace expiró", "sharing is disabled" => "compartir está desactivado", "For more info, please ask the person who sent this link." => "Para mayor información, contactá a la persona que te mandó el enlace.", -"%s shared the folder %s with you" => "%s compartió la carpeta %s con vos", -"%s shared the file %s with you" => "%s compartió el archivo %s con vos", "Download" => "Descargar", -"Upload" => "Subir", -"Cancel upload" => "Cancelar subida", -"No preview available for" => "La vista preliminar no está disponible para" +"Direct link" => "Vínculo directo" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/es_CL.php b/apps/files_sharing/l10n/es_CL.php index 31dc045870..083bc4d4e2 100644 --- a/apps/files_sharing/l10n/es_CL.php +++ b/apps/files_sharing/l10n/es_CL.php @@ -1,6 +1,6 @@ "Clave", -"Upload" => "Subir" +"Download" => "Descargar" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/es_MX.php b/apps/files_sharing/l10n/es_MX.php index 9100ef8b35..1a1ebe4b4c 100644 --- a/apps/files_sharing/l10n/es_MX.php +++ b/apps/files_sharing/l10n/es_MX.php @@ -1,5 +1,6 @@ "Compartido por {owner}", "This share is password-protected" => "Este elemento compartido esta protegido por contraseña", "The password is wrong. Try again." => "La contraseña introducida es errónea. Inténtelo de nuevo.", "Password" => "Contraseña", @@ -9,12 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "el enlace expiró", "sharing is disabled" => "compartir está desactivado", "For more info, please ask the person who sent this link." => "Para mayor información, contacte a la persona que le envió el enlace.", -"%s shared the folder %s with you" => "%s compartió la carpeta %s contigo", -"%s shared the file %s with you" => "%s compartió el archivo %s contigo", "Download" => "Descargar", -"Upload" => "Subir", -"Cancel upload" => "Cancelar subida", -"No preview available for" => "No hay vista previa disponible para", "Direct link" => "Enlace directo" ); $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 4b7f975e83..e95e627195 100644 --- a/apps/files_sharing/l10n/et_EE.php +++ b/apps/files_sharing/l10n/et_EE.php @@ -1,5 +1,6 @@ "Jagas {owner}", "This share is password-protected" => "See jagamine on parooliga kaitstud", "The password is wrong. Try again." => "Parool on vale. Proovi uuesti.", "Password" => "Parool", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "link on aegunud", "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.", -"%s shared the folder %s with you" => "%s jagas sinuga kausta %s", -"%s shared the file %s with you" => "%s jagas sinuga faili %s", "Download" => "Lae alla", -"Upload" => "Lae üles", -"Cancel upload" => "Tühista üleslaadimine", -"No preview available for" => "Eelvaadet pole saadaval", +"Download %s" => "Laadi alla %s", "Direct link" => "Otsene link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/eu.php b/apps/files_sharing/l10n/eu.php index 20de5a085a..8be7bcb2a4 100644 --- a/apps/files_sharing/l10n/eu.php +++ b/apps/files_sharing/l10n/eu.php @@ -1,5 +1,6 @@ "{owner}-k partekatuta", "This share is password-protected" => "Elkarbanatutako hau pasahitzarekin babestuta dago", "The password is wrong. Try again." => "Pasahitza ez da egokia. Saiatu berriro.", "Password" => "Pasahitza", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "lotura iraungi da", "sharing is disabled" => "elkarbanatzea ez dago gaituta", "For more info, please ask the person who sent this link." => "Informazio gehiagorako, mesedez eskatu lotura hau bidali zuen pertsonari", -"%s shared the folder %s with you" => "%sk zurekin %s karpeta elkarbanatu du", -"%s shared the file %s with you" => "%sk zurekin %s fitxategia elkarbanatu du", "Download" => "Deskargatu", -"Upload" => "Igo", -"Cancel upload" => "Ezeztatu igoera", -"No preview available for" => "Ez dago aurrebista eskuragarririk hauentzat ", +"Download %s" => "Deskargatu %s", "Direct link" => "Lotura zuzena" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/eu_ES.php b/apps/files_sharing/l10n/eu_ES.php new file mode 100644 index 0000000000..e6e5bc7cbf --- /dev/null +++ b/apps/files_sharing/l10n/eu_ES.php @@ -0,0 +1,5 @@ + "Deskargatu" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/fa.php b/apps/files_sharing/l10n/fa.php index 664338723c..1176401f1a 100644 --- a/apps/files_sharing/l10n/fa.php +++ b/apps/files_sharing/l10n/fa.php @@ -1,12 +1,8 @@ "اشتراک گذارنده {owner}", "The password is wrong. Try again." => "رمزعبور اشتباه می باشد. دوباره امتحان کنید.", "Password" => "گذرواژه", -"%s shared the folder %s with you" => "%sپوشه %s را با شما به اشتراک گذاشت", -"%s shared the file %s with you" => "%sفایل %s را با شما به اشتراک گذاشت", -"Download" => "دانلود", -"Upload" => "بارگزاری", -"Cancel upload" => "متوقف کردن بار گذاری", -"No preview available for" => "هیچگونه پیش نمایشی موجود نیست" +"Download" => "دانلود" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/fi_FI.php b/apps/files_sharing/l10n/fi_FI.php index c54c822b1c..851463c4b8 100644 --- a/apps/files_sharing/l10n/fi_FI.php +++ b/apps/files_sharing/l10n/fi_FI.php @@ -1,5 +1,6 @@ "Jakanut {owner}", "This share is password-protected" => "Tämä jako on suojattu salasanalla", "The password is wrong. Try again." => "Väärä salasana. Yritä uudelleen.", "Password" => "Salasana", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "linkki vanheni", "sharing is disabled" => "jakaminen on poistettu käytöstä", "For more info, please ask the person who sent this link." => "Kysy lisätietoja henkilöltä, jolta sait linkin.", -"%s shared the folder %s with you" => "%s jakoi kansion %s kanssasi", -"%s shared the file %s with you" => "%s jakoi tiedoston %s kanssasi", "Download" => "Lataa", -"Upload" => "Lähetä", -"Cancel upload" => "Peru lähetys", -"No preview available for" => "Ei esikatselua kohteelle", +"Download %s" => "Lataa %s", "Direct link" => "Suora linkki" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/fr.php b/apps/files_sharing/l10n/fr.php index b51f421fa5..a5b75e412f 100644 --- a/apps/files_sharing/l10n/fr.php +++ b/apps/files_sharing/l10n/fr.php @@ -1,5 +1,6 @@ "Partagé par {owner}", "This share is password-protected" => "Ce partage est protégé par un mot de passe", "The password is wrong. Try again." => "Le mot de passe est incorrect. Veuillez réessayer.", "Password" => "Mot de passe", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "le lien a expiré", "sharing is disabled" => "le partage est désactivé", "For more info, please ask the person who sent this link." => "Pour plus d'informations, veuillez contacter la personne qui a envoyé ce lien.", -"%s shared the folder %s with you" => "%s a partagé le répertoire %s avec vous", -"%s shared the file %s with you" => "%s a partagé le fichier %s avec vous", "Download" => "Télécharger", -"Upload" => "Envoyer", -"Cancel upload" => "Annuler l'envoi", -"No preview available for" => "Pas d'aperçu disponible pour", +"Download %s" => "Télécharger %s", "Direct link" => "Lien direct" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files_sharing/l10n/gl.php b/apps/files_sharing/l10n/gl.php index 3ea3fe5f1c..f5e1c6645f 100644 --- a/apps/files_sharing/l10n/gl.php +++ b/apps/files_sharing/l10n/gl.php @@ -1,5 +1,6 @@ "Compartido por {owner}", "This share is password-protected" => "Esta compartición está protexida con contrasinal", "The password is wrong. Try again." => "O contrasinal é incorrecto. Ténteo de novo.", "Password" => "Contrasinal", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "a ligazón caducou", "sharing is disabled" => "foi desactivada a compartición", "For more info, please ask the person who sent this link." => "Para obter máis información, pregúntelle á persoa que lle enviou a ligazón.", -"%s shared the folder %s with you" => "%s compartiu o cartafol %s con vostede", -"%s shared the file %s with you" => "%s compartiu o ficheiro %s con vostede", "Download" => "Descargar", -"Upload" => "Enviar", -"Cancel upload" => "Cancelar o envío", -"No preview available for" => "Sen vista previa dispoñíbel para", +"Download %s" => "Descargar %s", "Direct link" => "Ligazón directa" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/he.php b/apps/files_sharing/l10n/he.php index 217298fedd..e56fdb2c80 100644 --- a/apps/files_sharing/l10n/he.php +++ b/apps/files_sharing/l10n/he.php @@ -1,11 +1,7 @@ "שותף בידי {owner}", "Password" => "סיסמא", -"%s shared the folder %s with you" => "%s שיתף עמך את התיקייה %s", -"%s shared the file %s with you" => "%s שיתף עמך את הקובץ %s", -"Download" => "הורדה", -"Upload" => "העלאה", -"Cancel upload" => "ביטול ההעלאה", -"No preview available for" => "אין תצוגה מקדימה זמינה עבור" +"Download" => "הורדה" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/hi.php b/apps/files_sharing/l10n/hi.php index 63a5d528f3..74a2c32043 100644 --- a/apps/files_sharing/l10n/hi.php +++ b/apps/files_sharing/l10n/hi.php @@ -1,6 +1,5 @@ "पासवर्ड", -"Upload" => "अपलोड " +"Password" => "पासवर्ड" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/hr.php b/apps/files_sharing/l10n/hr.php index 4a82dd7f71..16776cdba2 100644 --- a/apps/files_sharing/l10n/hr.php +++ b/apps/files_sharing/l10n/hr.php @@ -1,8 +1,6 @@ "Lozinka", -"Download" => "Preuzimanje", -"Upload" => "Učitaj", -"Cancel upload" => "Prekini upload" +"Download" => "Preuzimanje" ); $PLURAL_FORMS = "nplurals=3; 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_sharing/l10n/hu_HU.php b/apps/files_sharing/l10n/hu_HU.php index a06c51b377..8221011610 100644 --- a/apps/files_sharing/l10n/hu_HU.php +++ b/apps/files_sharing/l10n/hu_HU.php @@ -1,5 +1,6 @@ "Megosztotta: {owner}", "This share is password-protected" => "Ez egy jelszóval védett megosztás", "The password is wrong. Try again." => "A megadott jelszó nem megfelelő. Próbálja újra!", "Password" => "Jelszó", @@ -9,12 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "lejárt a link érvényességi ideje", "sharing is disabled" => "letiltásra került a megosztás", "For more info, please ask the person who sent this link." => "További információért forduljon ahhoz, aki ezt a linket küldte Önnek!", -"%s shared the folder %s with you" => "%s megosztotta Önnel ezt a mappát: %s", -"%s shared the file %s with you" => "%s megosztotta Önnel ezt az állományt: %s", "Download" => "Letöltés", -"Upload" => "Feltöltés", -"Cancel upload" => "A feltöltés megszakítása", -"No preview available for" => "Nem áll rendelkezésre előnézet ehhez: ", "Direct link" => "Közvetlen link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/ia.php b/apps/files_sharing/l10n/ia.php index f9d6c33a0b..03e2deb431 100644 --- a/apps/files_sharing/l10n/ia.php +++ b/apps/files_sharing/l10n/ia.php @@ -1,7 +1,6 @@ "Contrasigno", -"Download" => "Discargar", -"Upload" => "Incargar" +"Download" => "Discargar" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/id.php b/apps/files_sharing/l10n/id.php index 865a951c2d..72670c23b3 100644 --- a/apps/files_sharing/l10n/id.php +++ b/apps/files_sharing/l10n/id.php @@ -1,5 +1,6 @@ "Dibagikan oleh {owner}", "This share is password-protected" => "Berbagi ini dilindungi sandi", "The password is wrong. Try again." => "Sandi salah. Coba lagi", "Password" => "Sandi", @@ -9,12 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "tautan telah kadaluarsa", "sharing is disabled" => "berbagi dinonaktifkan", "For more info, please ask the person who sent this link." => "Untuk info lebih lanjut, silakan tanyakan orang yang mengirim tautan ini.", -"%s shared the folder %s with you" => "%s membagikan folder %s dengan Anda", -"%s shared the file %s with you" => "%s membagikan berkas %s dengan Anda", "Download" => "Unduh", -"Upload" => "Unggah", -"Cancel upload" => "Batal unggah", -"No preview available for" => "Tidak ada pratinjau yang tersedia untuk", "Direct link" => "Tautan langsung" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/is.php b/apps/files_sharing/l10n/is.php index 8ae8e48eff..795dfeb6bf 100644 --- a/apps/files_sharing/l10n/is.php +++ b/apps/files_sharing/l10n/is.php @@ -1,11 +1,6 @@ "Lykilorð", -"%s shared the folder %s with you" => "%s deildi möppunni %s með þér", -"%s shared the file %s with you" => "%s deildi skránni %s með þér", -"Download" => "Niðurhal", -"Upload" => "Senda inn", -"Cancel upload" => "Hætta við innsendingu", -"No preview available for" => "Yfirlit ekki í boði fyrir" +"Download" => "Niðurhal" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/it.php b/apps/files_sharing/l10n/it.php index 7967b50d34..94c2a66808 100644 --- a/apps/files_sharing/l10n/it.php +++ b/apps/files_sharing/l10n/it.php @@ -1,5 +1,6 @@ "Condiviso da {owner}", "This share is password-protected" => "Questa condivione è protetta da password", "The password is wrong. Try again." => "La password è errata. Prova ancora.", "Password" => "Password", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "il collegamento è scaduto", "sharing is disabled" => "la condivisione è disabilitata", "For more info, please ask the person who sent this link." => "Per ulteriori informazioni, chiedi alla persona che ti ha inviato il collegamento.", -"%s shared the folder %s with you" => "%s ha condiviso la cartella %s con te", -"%s shared the file %s with you" => "%s ha condiviso il file %s con te", "Download" => "Scarica", -"Upload" => "Carica", -"Cancel upload" => "Annulla il caricamento", -"No preview available for" => "Nessuna anteprima disponibile per", +"Download %s" => "Scarica %s", "Direct link" => "Collegamento diretto" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/ja.php b/apps/files_sharing/l10n/ja.php new file mode 100644 index 0000000000..a45da97dca --- /dev/null +++ b/apps/files_sharing/l10n/ja.php @@ -0,0 +1,17 @@ + "{owner} と共有中", +"This share is password-protected" => "この共有はパスワードで保護されています", +"The password is wrong. Try again." => "パスワードが間違っています。再試行してください。", +"Password" => "パスワード", +"Sorry, this link doesn’t seem to work anymore." => "申し訳ございません。このリンクはもう利用できません。", +"Reasons might be:" => "理由は以下の通りと考えられます:", +"the item was removed" => "アイテムが削除されました", +"the link expired" => "リンクの期限が切れています", +"sharing is disabled" => "共有が無効になっています", +"For more info, please ask the person who sent this link." => "不明な点は、こちらのリンクの提供者に確認をお願いします。", +"Download" => "ダウンロード", +"Download %s" => "%s をダウンロード", +"Direct link" => "リンク" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/ja_JP.php b/apps/files_sharing/l10n/ja_JP.php index fe25cb5b6e..7e6461c608 100644 --- a/apps/files_sharing/l10n/ja_JP.php +++ b/apps/files_sharing/l10n/ja_JP.php @@ -1,5 +1,6 @@ "{owner} と共有中", "This share is password-protected" => "この共有はパスワードで保護されています", "The password is wrong. Try again." => "パスワードが間違っています。再試行してください。", "Password" => "パスワード", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "リンクの期限が切れています", "sharing is disabled" => "共有が無効になっています", "For more info, please ask the person who sent this link." => "不明な点は、こちらのリンクの提供者に確認をお願いします。", -"%s shared the folder %s with you" => "%s はフォルダー %s をあなたと共有中です", -"%s shared the file %s with you" => "%s はファイル %s をあなたと共有中です", -"Download" => "ダウンロード", -"Upload" => "アップロード", -"Cancel upload" => "アップロードをキャンセル", -"No preview available for" => "プレビューはありません", +"shared by %s" => "%s で共有中", +"Download %s" => "%s をダウンロード", "Direct link" => "リンク" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/jv.php b/apps/files_sharing/l10n/jv.php new file mode 100644 index 0000000000..690632bdba --- /dev/null +++ b/apps/files_sharing/l10n/jv.php @@ -0,0 +1,5 @@ + "Njipuk" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/ka_GE.php b/apps/files_sharing/l10n/ka_GE.php index 89a6800b3e..132bcb274c 100644 --- a/apps/files_sharing/l10n/ka_GE.php +++ b/apps/files_sharing/l10n/ka_GE.php @@ -1,11 +1,7 @@ "გაზიარდა {owner} –ის მიერ", "Password" => "პაროლი", -"%s shared the folder %s with you" => "%s–მა გაგიზიარათ ფოლდერი %s", -"%s shared the file %s with you" => "%s–მა გაგიზიარათ ფაილი %s", -"Download" => "ჩამოტვირთვა", -"Upload" => "ატვირთვა", -"Cancel upload" => "ატვირთვის გაუქმება", -"No preview available for" => "წინასწარი დათვალიერება შეუძლებელია" +"Download" => "ჩამოტვირთვა" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/km.php b/apps/files_sharing/l10n/km.php new file mode 100644 index 0000000000..db353c9cb7 --- /dev/null +++ b/apps/files_sharing/l10n/km.php @@ -0,0 +1,6 @@ + "ពាក្យសម្ងាត់", +"Download" => "ទាញយក" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/ko.php b/apps/files_sharing/l10n/ko.php index 03c4c1aea9..00818abf4a 100644 --- a/apps/files_sharing/l10n/ko.php +++ b/apps/files_sharing/l10n/ko.php @@ -1,5 +1,6 @@ "{owner} 님이 공유함", "This share is password-protected" => "이 공유는 암호로 보호되어 있습니다", "The password is wrong. Try again." => "암호가 잘못되었습니다. 다시 입력해 주십시오.", "Password" => "암호", @@ -9,12 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "링크가 만료됨", "sharing is disabled" => "공유가 비활성화됨", "For more info, please ask the person who sent this link." => "자세한 정보는 링크를 보낸 사람에게 문의하십시오.", -"%s shared the folder %s with you" => "%s 님이 폴더 %s을(를) 공유하였습니다", -"%s shared the file %s with you" => "%s 님이 파일 %s을(를) 공유하였습니다", "Download" => "다운로드", -"Upload" => "업로드", -"Cancel upload" => "업로드 취소", -"No preview available for" => "다음 항목을 미리 볼 수 없음:", "Direct link" => "직접 링크" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/ku_IQ.php b/apps/files_sharing/l10n/ku_IQ.php index 6b4b7e4ba9..b16e87d81c 100644 --- a/apps/files_sharing/l10n/ku_IQ.php +++ b/apps/files_sharing/l10n/ku_IQ.php @@ -1,10 +1,6 @@ "وشەی تێپەربو", -"%s shared the folder %s with you" => "%s دابه‌شی کردووه‌ بوخچه‌ی %s له‌گه‌ڵ تۆ", -"%s shared the file %s with you" => "%s دابه‌شی کردووه‌ په‌ڕگه‌یی %s له‌گه‌ڵ تۆ", -"Download" => "داگرتن", -"Upload" => "بارکردن", -"No preview available for" => "هیچ پێشبینیه‌ك ئاماده‌ نیه بۆ" +"Download" => "داگرتن" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/lb.php b/apps/files_sharing/l10n/lb.php index eeb6a3e2dc..a3e9813822 100644 --- a/apps/files_sharing/l10n/lb.php +++ b/apps/files_sharing/l10n/lb.php @@ -2,11 +2,6 @@ $TRANSLATIONS = array( "The password is wrong. Try again." => "Den Passwuert ass incorrect. Probeier ed nach eng keier.", "Password" => "Passwuert", -"%s shared the folder %s with you" => "%s huet den Dossier %s mad der gedeelt", -"%s shared the file %s with you" => "%s deelt den Fichier %s mad dir", -"Download" => "Download", -"Upload" => "Eroplueden", -"Cancel upload" => "Upload ofbriechen", -"No preview available for" => "Keeng Preview do fir" +"Download" => "Download" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/lt_LT.php b/apps/files_sharing/l10n/lt_LT.php index 3786fd08b9..4c05e9217a 100644 --- a/apps/files_sharing/l10n/lt_LT.php +++ b/apps/files_sharing/l10n/lt_LT.php @@ -1,5 +1,6 @@ "Bendrina {owner}", "This share is password-protected" => "Turinys apsaugotas slaptažodžiu", "The password is wrong. Try again." => "Netinka slaptažodis: Bandykite dar kartą.", "Password" => "Slaptažodis", @@ -9,12 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "baigėsi nuorodos galiojimo laikas", "sharing is disabled" => "dalinimasis yra išjungtas", "For more info, please ask the person who sent this link." => "Dėl tikslesnės informacijos susisiekite su asmeniu atsiuntusiu nuorodą.", -"%s shared the folder %s with you" => "%s pasidalino su jumis %s aplanku", -"%s shared the file %s with you" => "%s pasidalino su jumis %s failu", "Download" => "Atsisiųsti", -"Upload" => "Įkelti", -"Cancel upload" => "Atšaukti siuntimą", -"No preview available for" => "Peržiūra nėra galima", "Direct link" => "Tiesioginė nuoroda" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/apps/files_sharing/l10n/lv.php b/apps/files_sharing/l10n/lv.php index a913ba1152..693f91d3b5 100644 --- a/apps/files_sharing/l10n/lv.php +++ b/apps/files_sharing/l10n/lv.php @@ -1,11 +1,7 @@ "Dalījās {owner}", "Password" => "Parole", -"%s shared the folder %s with you" => "%s ar jums dalījās ar mapi %s", -"%s shared the file %s with you" => "%s ar jums dalījās ar datni %s", -"Download" => "Lejupielādēt", -"Upload" => "Augšupielādēt", -"Cancel upload" => "Atcelt augšupielādi", -"No preview available for" => "Nav pieejams priekšskatījums priekš" +"Download" => "Lejupielādēt" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"; diff --git a/apps/files_sharing/l10n/mk.php b/apps/files_sharing/l10n/mk.php index c132f7aa26..b7281825a8 100644 --- a/apps/files_sharing/l10n/mk.php +++ b/apps/files_sharing/l10n/mk.php @@ -1,11 +1,7 @@ "Споделени од {owner}", "Password" => "Лозинка", -"%s shared the folder %s with you" => "%s ја сподели папката %s со Вас", -"%s shared the file %s with you" => "%s ја сподели датотеката %s со Вас", -"Download" => "Преземи", -"Upload" => "Подигни", -"Cancel upload" => "Откажи прикачување", -"No preview available for" => "Нема достапно преглед за" +"Download" => "Преземи" ); $PLURAL_FORMS = "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"; diff --git a/apps/files_sharing/l10n/ms_MY.php b/apps/files_sharing/l10n/ms_MY.php index 9725dd4d1b..43ea0b2d88 100644 --- a/apps/files_sharing/l10n/ms_MY.php +++ b/apps/files_sharing/l10n/ms_MY.php @@ -1,8 +1,6 @@ "Kata laluan", -"Download" => "Muat turun", -"Upload" => "Muat naik", -"Cancel upload" => "Batal muat naik" +"Download" => "Muat turun" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/nb_NO.php b/apps/files_sharing/l10n/nb_NO.php index 0452b5275c..193ee7165e 100644 --- a/apps/files_sharing/l10n/nb_NO.php +++ b/apps/files_sharing/l10n/nb_NO.php @@ -1,12 +1,16 @@ "Delt av {owner}", +"This share is password-protected" => "Denne delingen er passordbeskyttet", "The password is wrong. Try again." => "Passordet er feil. Prøv på nytt.", "Password" => "Passord", -"%s shared the folder %s with you" => "%s delte mappen %s med deg", -"%s shared the file %s with you" => "%s delte filen %s med deg", +"Sorry, this link doesn’t seem to work anymore." => "Beklager, denne lenken ser ikke ut til å virke lenger.", +"Reasons might be:" => "Mulige årsaker:", +"the item was removed" => "elementet er fjernet", +"the link expired" => "lenken er utløpt", +"sharing is disabled" => "deling er deaktivert", +"For more info, please ask the person who sent this link." => "For mer informasjon, spør personen som sendte lenken.", "Download" => "Last ned", -"Upload" => "Last opp", -"Cancel upload" => "Avbryt opplasting", -"No preview available for" => "Forhåndsvisning ikke tilgjengelig for" +"Direct link" => "Direkte lenke" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/nl.php b/apps/files_sharing/l10n/nl.php index 687c6e134f..e35898862c 100644 --- a/apps/files_sharing/l10n/nl.php +++ b/apps/files_sharing/l10n/nl.php @@ -1,5 +1,6 @@ "Gedeeld door {owner}", "This share is password-protected" => "Deze share is met een wachtwoord beveiligd", "The password is wrong. Try again." => "Wachtwoord ongeldig. Probeer het nogmaals.", "Password" => "Wachtwoord", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "de link is verlopen", "sharing is disabled" => "delen is uitgeschakeld", "For more info, please ask the person who sent this link." => "Voor meer informatie, neem contact op met de persoon die u deze link heeft gestuurd.", -"%s shared the folder %s with you" => "%s deelt de map %s met u", -"%s shared the file %s with you" => "%s deelt het bestand %s met u", "Download" => "Downloaden", -"Upload" => "Uploaden", -"Cancel upload" => "Upload afbreken", -"No preview available for" => "Geen voorbeeldweergave beschikbaar voor", +"Download %s" => "Download %s", "Direct link" => "Directe link" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/nn_NO.php b/apps/files_sharing/l10n/nn_NO.php index 1f1e8001e7..e85c019d5c 100644 --- a/apps/files_sharing/l10n/nn_NO.php +++ b/apps/files_sharing/l10n/nn_NO.php @@ -1,5 +1,6 @@ "Delt av {owner}", "The password is wrong. Try again." => "Passordet er gale. Prøv igjen.", "Password" => "Passord", "Sorry, this link doesn’t seem to work anymore." => "Orsak, denne lenkja fungerer visst ikkje lenger.", @@ -8,11 +9,6 @@ $TRANSLATIONS = array( "the link expired" => "lenkja har gått ut på dato", "sharing is disabled" => "deling er slått av", "For more info, please ask the person who sent this link." => "Spør den som sende deg lenkje om du vil ha meir informasjon.", -"%s shared the folder %s with you" => "%s delte mappa %s med deg", -"%s shared the file %s with you" => "%s delte fila %s med deg", -"Download" => "Last ned", -"Upload" => "Last opp", -"Cancel upload" => "Avbryt opplasting", -"No preview available for" => "Inga førehandsvising tilgjengeleg for" +"Download" => "Last ned" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/oc.php b/apps/files_sharing/l10n/oc.php index 299d98e58b..15ef1720ad 100644 --- a/apps/files_sharing/l10n/oc.php +++ b/apps/files_sharing/l10n/oc.php @@ -1,8 +1,6 @@ "Senhal", -"Download" => "Avalcarga", -"Upload" => "Amontcarga", -"Cancel upload" => " Anulla l'amontcargar" +"Download" => "Avalcarga" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files_sharing/l10n/pa.php b/apps/files_sharing/l10n/pa.php index 6c14eda59d..43632737a2 100644 --- a/apps/files_sharing/l10n/pa.php +++ b/apps/files_sharing/l10n/pa.php @@ -1,8 +1,6 @@ "ਪਾਸਵਰ", -"Download" => "ਡਾਊਨਲੋਡ", -"Upload" => "ਅੱਪਲੋਡ", -"Cancel upload" => "ਅੱਪਲੋਡ ਰੱਦ ਕਰੋ" +"Download" => "ਡਾਊਨਲੋਡ" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/pl.php b/apps/files_sharing/l10n/pl.php index 4c7498ee1b..bf62ead107 100644 --- a/apps/files_sharing/l10n/pl.php +++ b/apps/files_sharing/l10n/pl.php @@ -1,5 +1,6 @@ "Udostępnione przez {owner}", "This share is password-protected" => "Udział ten jest chroniony hasłem", "The password is wrong. Try again." => "To hasło jest niewłaściwe. Spróbuj ponownie.", "Password" => "Hasło", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "link wygasł", "sharing is disabled" => "Udostępnianie jest wyłączone", "For more info, please ask the person who sent this link." => "Aby uzyskać więcej informacji proszę poprosić osobę, która wysłał ten link.", -"%s shared the folder %s with you" => "%s współdzieli folder z tobą %s", -"%s shared the file %s with you" => "%s współdzieli z tobą plik %s", "Download" => "Pobierz", -"Upload" => "Wyślij", -"Cancel upload" => "Anuluj wysyłanie", -"No preview available for" => "Podgląd nie jest dostępny dla", +"Download %s" => "Pobierz %s", "Direct link" => "Bezpośredni link" ); $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_sharing/l10n/pt_BR.php b/apps/files_sharing/l10n/pt_BR.php index ee03749795..7167f99c2d 100644 --- a/apps/files_sharing/l10n/pt_BR.php +++ b/apps/files_sharing/l10n/pt_BR.php @@ -1,5 +1,6 @@ "Compartilhado por {owner}", "This share is password-protected" => "Este compartilhamento esta protegido por senha", "The password is wrong. Try again." => "Senha incorreta. Tente novamente.", "Password" => "Senha", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "o link expirou", "sharing is disabled" => "compartilhamento está desativada", "For more info, please ask the person who sent this link." => "Para mais informações, por favor, pergunte a pessoa que enviou este link.", -"%s shared the folder %s with you" => "%s compartilhou a pasta %s com você", -"%s shared the file %s with you" => "%s compartilhou o arquivo %s com você", "Download" => "Baixar", -"Upload" => "Upload", -"Cancel upload" => "Cancelar upload", -"No preview available for" => "Nenhuma visualização disponível para", +"Download %s" => "Baixar %s", "Direct link" => "Link direto" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files_sharing/l10n/pt_PT.php b/apps/files_sharing/l10n/pt_PT.php index cd94211b5d..b28e2b188d 100644 --- a/apps/files_sharing/l10n/pt_PT.php +++ b/apps/files_sharing/l10n/pt_PT.php @@ -1,5 +1,6 @@ "Partilhado por {owner}", "This share is password-protected" => "Esta partilha está protegida por palavra-chave", "The password is wrong. Try again." => "Password errada, por favor tente de novo", "Password" => "Palavra-passe", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "O link expirou", "sharing is disabled" => "A partilha está desativada", "For more info, please ask the person who sent this link." => "Para mais informações, por favor questione a pessoa que lhe enviou este link", -"%s shared the folder %s with you" => "%s partilhou a pasta %s consigo", -"%s shared the file %s with you" => "%s partilhou o ficheiro %s consigo", "Download" => "Transferir", -"Upload" => "Carregar", -"Cancel upload" => "Cancelar envio", -"No preview available for" => "Não há pré-visualização para", +"Download %s" => "Download %s", "Direct link" => "Link direto" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/ro.php b/apps/files_sharing/l10n/ro.php index 54e20ed6bb..024011bf29 100644 --- a/apps/files_sharing/l10n/ro.php +++ b/apps/files_sharing/l10n/ro.php @@ -2,11 +2,6 @@ $TRANSLATIONS = array( "The password is wrong. Try again." => "Parola este incorectă. Încercaţi din nou.", "Password" => "Parolă", -"%s shared the folder %s with you" => "%s a partajat directorul %s cu tine", -"%s shared the file %s with you" => "%s a partajat fișierul %s cu tine", -"Download" => "Descarcă", -"Upload" => "Încărcare", -"Cancel upload" => "Anulează încărcarea", -"No preview available for" => "Nici o previzualizare disponibilă pentru " +"Download" => "Descarcă" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"; diff --git a/apps/files_sharing/l10n/ru.php b/apps/files_sharing/l10n/ru.php index 8c48096f66..41c60d2ec8 100644 --- a/apps/files_sharing/l10n/ru.php +++ b/apps/files_sharing/l10n/ru.php @@ -1,20 +1,16 @@ "Эта шара защищена паролем", +"Shared by {owner}" => "Доступ открыл {owner}", +"This share is password-protected" => "Общий ресурс защищён паролем", "The password is wrong. Try again." => "Неверный пароль. Попробуйте еще раз.", "Password" => "Пароль", "Sorry, this link doesn’t seem to work anymore." => "К сожалению, эта ссылка, похоже не будет работать больше.", "Reasons might be:" => "Причиной может быть:", "the item was removed" => "объект был удалён", "the link expired" => "срок ссылки истёк", -"sharing is disabled" => "обмен отключен", -"For more info, please ask the person who sent this link." => "Для получения дополнительной информации, пожалуйста, спросите того кто отослал данную ссылку.", -"%s shared the folder %s with you" => "%s открыл доступ к папке %s для Вас", -"%s shared the file %s with you" => "%s открыл доступ к файлу %s для Вас", +"sharing is disabled" => "общий доступ отключён", +"For more info, please ask the person who sent this link." => "Пожалуйста, обратитесь к отправителю данной ссылки.", "Download" => "Скачать", -"Upload" => "Загрузка", -"Cancel upload" => "Отмена загрузки", -"No preview available for" => "Предпросмотр недоступен для", "Direct link" => "Прямая ссылка" ); $PLURAL_FORMS = "nplurals=3; 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_sharing/l10n/si_LK.php b/apps/files_sharing/l10n/si_LK.php index e840138564..da0390033a 100644 --- a/apps/files_sharing/l10n/si_LK.php +++ b/apps/files_sharing/l10n/si_LK.php @@ -1,11 +1,6 @@ "මුර පදය", -"%s shared the folder %s with you" => "%s ඔබව %s ෆෝල්ඩරයට හවුල් කරගත්තේය", -"%s shared the file %s with you" => "%s ඔබ සමඟ %s ගොනුව බෙදාහදාගත්තේය", -"Download" => "බාන්න", -"Upload" => "උඩුගත කරන්න", -"Cancel upload" => "උඩුගත කිරීම අත් හරින්න", -"No preview available for" => "පූර්වදර්ශනයක් නොමැත" +"Download" => "බාන්න" ); $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 4ea8cbdd77..48054b6c7a 100644 --- a/apps/files_sharing/l10n/sk_SK.php +++ b/apps/files_sharing/l10n/sk_SK.php @@ -1,5 +1,6 @@ "Zdieľa {owner}", "This share is password-protected" => "Toto zdieľanie je chránené heslom", "The password is wrong. Try again." => "Heslo je chybné. Skúste to znova.", "Password" => "Heslo", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "linke vypršala platnosť", "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.", -"%s shared the folder %s with you" => "%s zdieľa s vami priečinok %s", -"%s shared the file %s with you" => "%s zdieľa s vami súbor %s", "Download" => "Sťahovanie", -"Upload" => "Nahrať", -"Cancel upload" => "Zrušiť nahrávanie", -"No preview available for" => "Žiaden náhľad k dispozícii pre", +"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/sl.php b/apps/files_sharing/l10n/sl.php index d5ef46e180..361f2f1b04 100644 --- a/apps/files_sharing/l10n/sl.php +++ b/apps/files_sharing/l10n/sl.php @@ -1,5 +1,6 @@ "Souporabo omogoča {owner}", "This share is password-protected" => "To mesto je zaščiteno z geslom.", "The password is wrong. Try again." => "Geslo je napačno. Poskusite znova.", "Password" => "Geslo", @@ -9,12 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "povezava je pretekla,", "sharing is disabled" => "souporaba je onemogočena.", "For more info, please ask the person who sent this link." => "Za več podrobnosti stopite v stik s pošiljateljem te povezave.", -"%s shared the folder %s with you" => "Oseba %s je določila mapo %s za souporabo", -"%s shared the file %s with you" => "Oseba %s je določila datoteko %s za souporabo", "Download" => "Prejmi", -"Upload" => "Pošlji", -"Cancel upload" => "Prekliči pošiljanje", -"No preview available for" => "Predogled ni na voljo za", +"Download %s" => "Prejmi %s", "Direct link" => "Neposredna povezava" ); $PLURAL_FORMS = "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"; diff --git a/apps/files_sharing/l10n/sq.php b/apps/files_sharing/l10n/sq.php index 473049f75e..f6729dafc3 100644 --- a/apps/files_sharing/l10n/sq.php +++ b/apps/files_sharing/l10n/sq.php @@ -1,5 +1,6 @@ "Kjo pjesë është e mbrojtur me fjalëkalim", "The password is wrong. Try again." => "Kodi është i gabuar. Provojeni përsëri.", "Password" => "Kodi", "Sorry, this link doesn’t seem to work anymore." => "Ju kërkojmë ndjesë, kjo lidhje duket sikur nuk punon më.", @@ -8,11 +9,7 @@ $TRANSLATIONS = array( "the link expired" => "lidhja ka skaduar", "sharing is disabled" => "ndarja është çaktivizuar", "For more info, please ask the person who sent this link." => "Për më shumë informacione, ju lutem pyesni personin që iu dërgoi këtë lidhje.", -"%s shared the folder %s with you" => "%s ndau me ju dosjen %s", -"%s shared the file %s with you" => "%s ndau me ju skedarin %s", "Download" => "Shkarko", -"Upload" => "Ngarko", -"Cancel upload" => "Anulo ngarkimin", -"No preview available for" => "Shikimi paraprak nuk është i mundur për" +"Direct link" => "Lidhje direkte" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/sr.php b/apps/files_sharing/l10n/sr.php index e484ad25eb..947e57551a 100644 --- a/apps/files_sharing/l10n/sr.php +++ b/apps/files_sharing/l10n/sr.php @@ -1,8 +1,6 @@ "Лозинка", -"Download" => "Преузми", -"Upload" => "Отпреми", -"Cancel upload" => "Прекини отпремање" +"Download" => "Преузми" ); $PLURAL_FORMS = "nplurals=3; 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_sharing/l10n/sr@latin.php b/apps/files_sharing/l10n/sr@latin.php index 08463e1510..f44821fc0d 100644 --- a/apps/files_sharing/l10n/sr@latin.php +++ b/apps/files_sharing/l10n/sr@latin.php @@ -1,7 +1,6 @@ "Lozinka", -"Download" => "Preuzmi", -"Upload" => "Pošalji" +"Download" => "Preuzmi" ); $PLURAL_FORMS = "nplurals=3; 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_sharing/l10n/sv.php b/apps/files_sharing/l10n/sv.php index 055ef552d6..a1951401d7 100644 --- a/apps/files_sharing/l10n/sv.php +++ b/apps/files_sharing/l10n/sv.php @@ -1,5 +1,6 @@ "Delad av {owner}", "This share is password-protected" => "Den här delningen är lösenordsskyddad", "The password is wrong. Try again." => "Lösenordet är fel. Försök igen.", "Password" => "Lösenord", @@ -9,12 +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.", -"%s shared the folder %s with you" => "%s delade mappen %s med dig", -"%s shared the file %s with you" => "%s delade filen %s med dig", "Download" => "Ladda ner", -"Upload" => "Ladda upp", -"Cancel upload" => "Avbryt uppladdning", -"No preview available for" => "Ingen förhandsgranskning tillgänglig för", +"Download %s" => "Ladda ner %s", "Direct link" => "Direkt länk" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/ta_LK.php b/apps/files_sharing/l10n/ta_LK.php index 90a2fb417f..05443e0522 100644 --- a/apps/files_sharing/l10n/ta_LK.php +++ b/apps/files_sharing/l10n/ta_LK.php @@ -1,11 +1,7 @@ "பகிரப்பட்டது {சொந்தகாரர்}", "Password" => "கடவுச்சொல்", -"%s shared the folder %s with you" => "%s கோப்புறையானது %s உடன் பகிரப்பட்டது", -"%s shared the file %s with you" => "%s கோப்பானது %s உடன் பகிரப்பட்டது", -"Download" => "பதிவிறக்குக", -"Upload" => "பதிவேற்றுக", -"Cancel upload" => "பதிவேற்றலை இரத்து செய்க", -"No preview available for" => "அதற்கு முன்னோக்கு ஒன்றும் இல்லை" +"Download" => "பதிவிறக்குக" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/th_TH.php b/apps/files_sharing/l10n/th_TH.php index e192e0a97c..f2f90088da 100644 --- a/apps/files_sharing/l10n/th_TH.php +++ b/apps/files_sharing/l10n/th_TH.php @@ -1,11 +1,7 @@ "ถูกแชร์โดย {owner}", "Password" => "รหัสผ่าน", -"%s shared the folder %s with you" => "%s ได้แชร์โฟลเดอร์ %s ให้กับคุณ", -"%s shared the file %s with you" => "%s ได้แชร์ไฟล์ %s ให้กับคุณ", -"Download" => "ดาวน์โหลด", -"Upload" => "อัพโหลด", -"Cancel upload" => "ยกเลิกการอัพโหลด", -"No preview available for" => "ไม่สามารถดูตัวอย่างได้สำหรับ" +"Download" => "ดาวน์โหลด" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/tr.php b/apps/files_sharing/l10n/tr.php index 22fe8ed020..ac3cb52656 100644 --- a/apps/files_sharing/l10n/tr.php +++ b/apps/files_sharing/l10n/tr.php @@ -1,20 +1,17 @@ "{owner} tarafından paylaşılmış", "This share is password-protected" => "Bu paylaşım parola korumalı", "The password is wrong. Try again." => "Parola hatalı. Yeniden deneyin.", "Password" => "Parola", -"Sorry, this link doesn’t seem to work anymore." => "Üzgünüz, bu bağlantı artık çalışıyor gibi görünmüyor", +"Sorry, this link doesn’t seem to work anymore." => "Üzgünüz, bu bağlantı artık çalışıyor gibi görünmüyor.", "Reasons might be:" => "Sebepleri şunlar olabilir:", "the item was removed" => "öge kaldırılmış", "the link expired" => "bağlantı süresi dolmuş", "sharing is disabled" => "paylaşım devre dışı", "For more info, please ask the person who sent this link." => "Daha fazla bilgi için bu bağlantıyı aldığınız kişi ile iletişime geçin.", -"%s shared the folder %s with you" => "%s, %s klasörünü sizinle paylaştı", -"%s shared the file %s with you" => "%s, %s dosyasını sizinle paylaştı", "Download" => "İndir", -"Upload" => "Yükle", -"Cancel upload" => "Yüklemeyi iptal et", -"No preview available for" => "Kullanılabilir önizleme yok", +"Download %s" => "İndir: %s", "Direct link" => "Doğrudan bağlantı" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/apps/files_sharing/l10n/ug.php b/apps/files_sharing/l10n/ug.php index 6ffa02f734..fd6a1c71c9 100644 --- a/apps/files_sharing/l10n/ug.php +++ b/apps/files_sharing/l10n/ug.php @@ -1,8 +1,6 @@ "ئىم", -"Download" => "چۈشۈر", -"Upload" => "يۈكلە", -"Cancel upload" => "يۈكلەشتىن ۋاز كەچ" +"Download" => "چۈشۈر" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/uk.php b/apps/files_sharing/l10n/uk.php index 842b4b8d96..7b0acb661b 100644 --- a/apps/files_sharing/l10n/uk.php +++ b/apps/files_sharing/l10n/uk.php @@ -1,5 +1,6 @@ "Опублікував {owner}", "This share is password-protected" => "Цей ресурс обміну захищений паролем", "The password is wrong. Try again." => "Невірний пароль. Спробуйте ще раз.", "Password" => "Пароль", @@ -9,12 +10,7 @@ $TRANSLATIONS = array( "the link expired" => "посилання застаріло", "sharing is disabled" => "обмін заборонений", "For more info, please ask the person who sent this link." => "Для отримання додаткової інформації, будь ласка, зверніться до особи, яка надіслала це посилання.", -"%s shared the folder %s with you" => "%s опублікував каталог %s для Вас", -"%s shared the file %s with you" => "%s опублікував файл %s для Вас", "Download" => "Завантажити", -"Upload" => "Вивантажити", -"Cancel upload" => "Перервати завантаження", -"No preview available for" => "Попередній перегляд недоступний для", "Direct link" => "Пряме посилання" ); $PLURAL_FORMS = "nplurals=3; 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_sharing/l10n/vi.php b/apps/files_sharing/l10n/vi.php index 4566d3744d..1db740c023 100644 --- a/apps/files_sharing/l10n/vi.php +++ b/apps/files_sharing/l10n/vi.php @@ -1,11 +1,7 @@ "Được chia sẽ bởi {owner}", "Password" => "Mật khẩu", -"%s shared the folder %s with you" => "%s đã chia sẻ thư mục %s với bạn", -"%s shared the file %s with you" => "%s đã chia sẻ tập tin %s với bạn", -"Download" => "Tải về", -"Upload" => "Tải lên", -"Cancel upload" => "Hủy upload", -"No preview available for" => "Không có xem trước cho" +"Download" => "Tải về" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/zh_CN.php b/apps/files_sharing/l10n/zh_CN.php index 956c161b48..5cc95b71af 100644 --- a/apps/files_sharing/l10n/zh_CN.php +++ b/apps/files_sharing/l10n/zh_CN.php @@ -1,5 +1,7 @@ "由{owner}共享", +"This share is password-protected" => "这是一个密码保护的共享", "The password is wrong. Try again." => "用户名或密码错误!请重试", "Password" => "密码", "Sorry, this link doesn’t seem to work anymore." => "抱歉,此链接已失效", @@ -8,11 +10,8 @@ $TRANSLATIONS = array( "the link expired" => "链接过期", "sharing is disabled" => "共享已禁用", "For more info, please ask the person who sent this link." => "欲知详情,请联系发给你链接的人。", -"%s shared the folder %s with you" => "%s与您共享了%s文件夹", -"%s shared the file %s with you" => "%s与您共享了%s文件", "Download" => "下载", -"Upload" => "上传", -"Cancel upload" => "取消上传", -"No preview available for" => "没有预览" +"Download %s" => "下载 %s", +"Direct link" => "直接链接" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/zh_HK.php b/apps/files_sharing/l10n/zh_HK.php index 434420264e..3c561acce4 100644 --- a/apps/files_sharing/l10n/zh_HK.php +++ b/apps/files_sharing/l10n/zh_HK.php @@ -1,7 +1,6 @@ "密碼", -"Download" => "下載", -"Upload" => "上傳" +"Download" => "下載" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/l10n/zh_TW.php b/apps/files_sharing/l10n/zh_TW.php index 3854b7ae58..07abcb6999 100644 --- a/apps/files_sharing/l10n/zh_TW.php +++ b/apps/files_sharing/l10n/zh_TW.php @@ -1,5 +1,6 @@ "由 {owner} 分享", "This share is password-protected" => "這個分享有密碼保護", "The password is wrong. Try again." => "請檢查您的密碼並再試一次", "Password" => "密碼", @@ -9,11 +10,6 @@ $TRANSLATIONS = array( "the link expired" => "連結過期", "sharing is disabled" => "分享功能已停用", "For more info, please ask the person who sent this link." => "請詢問告訴您此連結的人以瞭解更多", -"%s shared the folder %s with you" => "%s 和您分享了資料夾 %s ", -"%s shared the file %s with you" => "%s 和您分享了檔案 %s", -"Download" => "下載", -"Upload" => "上傳", -"Cancel upload" => "取消上傳", -"No preview available for" => "無法預覽" +"Download" => "下載" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_sharing/lib/api.php b/apps/files_sharing/lib/api.php index 19a2d22b06..438d3cc4ba 100644 --- a/apps/files_sharing/lib/api.php +++ b/apps/files_sharing/lib/api.php @@ -68,7 +68,7 @@ class Api { public static function getShare($params) { $s = self::getShareFromId($params['id']); - $params['itemSource'] = $s['item_source']; + $params['itemSource'] = $s['file_source']; $params['itemType'] = $s['item_type']; $params['specificShare'] = true; @@ -98,8 +98,14 @@ class Api { break; } } + } else { + $path = $params['path']; + foreach ($shares as $key => $share) { + $shares[$key]['path'] = $path; + } } + // include also reshares in the lists. This means that the result // will contain every user with access to the file. if (isset($params['reshares']) && $params['reshares'] === true) { @@ -107,8 +113,10 @@ class Api { } if ($receivedFrom) { - $shares['received_from'] = $receivedFrom['uid_owner']; - $shares['received_from_displayname'] = \OCP\User::getDisplayName($receivedFrom['uid_owner']); + foreach ($shares as $key => $share) { + $shares[$key]['received_from'] = $receivedFrom['uid_owner']; + $shares[$key]['received_from_displayname'] = \OCP\User::getDisplayName($receivedFrom['uid_owner']); + } } } else { $shares = null; @@ -172,12 +180,14 @@ class Api { // workaround because folders are named 'dir' in this context $itemType = $file['type'] === 'file' ? 'file' : 'folder'; $share = \OCP\Share::getItemShared($itemType, $file['fileid']); - $receivedFrom = \OCP\Share::getItemSharedWithBySource($itemType, $file['fileid']); - if ($receivedFrom) { - $share['received_from'] = $receivedFrom['uid_owner']; - $share['received_from_displayname'] = \OCP\User::getDisplayName($receivedFrom['uid_owner']); - } - if ($share) { + if($share) { + $receivedFrom = \OCP\Share::getItemSharedWithBySource($itemType, $file['fileid']); + reset($share); + $key = key($share); + if ($receivedFrom) { + $share[$key]['received_from'] = $receivedFrom['uid_owner']; + $share[$key]['received_from_displayname'] = \OCP\User::getDisplayName($receivedFrom['uid_owner']); + } $result = array_merge($result, $share); } } @@ -281,9 +291,8 @@ class Api { public static function updateShare($params) { $share = self::getShareFromId($params['id']); - $itemSource = isset($share['item_source']) ? $share['item_source'] : null; - if($itemSource === null) { + if(!isset($share['file_source'])) { return new \OC_OCS_Result(null, 404, "wrong share Id, share doesn't exist."); } @@ -431,10 +440,10 @@ class Api { public static function deleteShare($params) { $share = self::getShareFromId($params['id']); - $itemSource = isset($share['item_source']) ? $share['item_source'] : null; + $fileSource = isset($share['file_source']) ? $share['file_source'] : null; $itemType = isset($share['item_type']) ? $share['item_type'] : null;; - if($itemSource === null) { + if($fileSource === null) { return new \OC_OCS_Result(null, 404, "wrong share ID, share doesn't exist."); } @@ -448,7 +457,7 @@ class Api { try { $return = \OCP\Share::unshare( $itemType, - $itemSource, + $fileSource, $shareType, $shareWith); } catch (\Exception $e) { @@ -504,7 +513,7 @@ class Api { * @return array with: item_source, share_type, share_with, item_type, permissions */ private static function getShareFromId($shareID) { - $sql = 'SELECT `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; + $sql = 'SELECT `file_source`, `item_source`, `share_type`, `share_with`, `item_type`, `permissions` FROM `*PREFIX*share` WHERE `id` = ?'; $args = array($shareID); $query = \OCP\DB::prepare($sql); $result = $query->execute($args); diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 4b0da0b002..1f316301c4 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -2,8 +2,9 @@ /** * ownCloud * - * @author Michael Gapczynski - * @copyright 2012 Michael Gapczynski mtgap@owncloud.com + * @author Bjoern Schiessle, Michael Gapczynski + * @copyright 2012 Michael Gapczynski + * 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 @@ -20,6 +21,7 @@ */ namespace OC\Files\Cache; + use OCP\Share_Backend_Collection; /** @@ -45,12 +47,15 @@ class Shared_Cache extends Cache { * @return \OC\Files\Cache\Cache */ private function getSourceCache($target) { - $source = \OC_Share_Backend_File::getSource($target); + if ($target === false || $target === $this->storage->getMountPoint()) { + $target = ''; + } + $source = \OC_Share_Backend_File::getSource($target, $this->storage->getMountPoint(), $this->storage->getItemType()); if (isset($source['path']) && isset($source['fileOwner'])) { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); - $mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']); - if (is_array($mount)) { - $fullPath = $mount[key($mount)]->getMountPoint().$source['path']; + $mounts = \OC\Files\Filesystem::getMountByNumericId($source['storage']); + if (is_array($mounts) and !empty($mounts)) { + $fullPath = $mounts[0]->getMountPoint() . $source['path']; list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); if ($storage) { $this->files[$target] = $internalPath; @@ -75,29 +80,34 @@ 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) { - if ($file == '') { - $data = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT); - $etag = \OCP\Config::getUserValue(\OCP\User::getUser(), 'files_sharing', 'etag'); - if (!isset($etag)) { - $etag = $this->storage->getETag(''); - \OCP\Config::setUserValue(\OCP\User::getUser(), 'files_sharing', 'etag', $etag); - } - $data['etag'] = $etag; - return $data; - } else if (is_string($file)) { - if ($cache = $this->getSourceCache($file)) { - return $cache->get($this->files[$file]); + if (is_string($file)) { + $cache = $this->getSourceCache($file); + if ($cache) { + $data = $cache->get($this->files[$file]); + $data['displayname_owner'] = \OC_User::getDisplayName($this->storage->getSharedFrom()); + $data['path'] = $file; + if ($file === '') { + $data['is_share_mount_point'] = true; + } + $data['uid_owner'] = $this->storage->getOwner($file); + return $data; } } else { + $sourceId = $file; + // if we are at the root of the mount point we want to return the + // cache information for the source item + if (!is_int($sourceId) || $sourceId === 0) { + $sourceId = $this->storage->getSourceId(); + } $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`,' - .' `size`, `mtime`, `encrypted`, `unencrypted_size`' - .' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); - $result = $query->execute(array($file)); + . ' `size`, `mtime`, `encrypted`, `unencrypted_size`, `storage_mtime`, `etag`' + . ' FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + $result = $query->execute(array($sourceId)); $data = $result->fetchRow(); $data['fileid'] = (int)$data['fileid']; $data['mtime'] = (int)$data['mtime']; @@ -114,6 +124,11 @@ class Shared_Cache extends Cache { } else { $data['size'] = (int)$data['size']; } + if (!is_int($file) || $file === 0) { + $data['path'] = ''; + $data['name'] = basename($this->storage->getMountPoint()); + $data['is_share_mount_point'] = true; + } return $data; } return false; @@ -126,25 +141,26 @@ class Shared_Cache extends Cache { * @return array */ public function getFolderContents($folder) { - if ($folder == '') { - $files = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS); - foreach ($files as &$file) { - $file['mimetype'] = $this->getMimetype($file['mimetype']); - $file['mimepart'] = $this->getMimetype($file['mimepart']); - $file['usersPath'] = 'files/Shared/' . ltrim($file['path'], '/'); - } - return $files; - } else { - $cache = $this->getSourceCache($folder); - if ($cache) { - $sourceFolderContent = $cache->getFolderContents($this->files[$folder]); - foreach ($sourceFolderContent as $key => $c) { - $sourceFolderContent[$key]['usersPath'] = 'files/Shared/' . $folder . '/' . $c['name']; - } - return $sourceFolderContent; - } + if ($folder === false) { + $folder = ''; } + + $dir = ($folder !== '') ? $folder . '/' : ''; + + $cache = $this->getSourceCache($folder); + if ($cache) { + $parent = $this->storage->getFile($folder); + $sourceFolderContent = $cache->getFolderContents($this->files[$folder]); + foreach ($sourceFolderContent as $key => $c) { + $sourceFolderContent[$key]['path'] = $dir . $c['name']; + $sourceFolderContent[$key]['uid_owner'] = $parent['uid_owner']; + $sourceFolderContent[$key]['displayname_owner'] = $parent['uid_owner']; + } + + return $sourceFolderContent; + } + return false; } @@ -157,9 +173,8 @@ class Shared_Cache extends Cache { * @return int file id */ public function put($file, array $data) { - if ($file === '' && isset($data['etag'])) { - return \OCP\Config::setUserValue(\OCP\User::getUser(), 'files_sharing', 'etag', $data['etag']); - } else if ($cache = $this->getSourceCache($file)) { + $file = ($file === false) ? '' : $file; + if ($cache = $this->getSourceCache($file)) { return $cache->put($this->files[$file], $data); } return false; @@ -172,7 +187,11 @@ class Shared_Cache extends Cache { * @return int */ public function getId($file) { - if ($cache = $this->getSourceCache($file)) { + if ($file === false) { + return $this->storage->getSourceId(); + } + $cache = $this->getSourceCache($file); + if ($cache) { return $cache->getId($this->files[$file]); } return -1; @@ -197,6 +216,7 @@ class Shared_Cache extends Cache { * @param string $file */ public function remove($file) { + $file = ($file === false) ? '' : $file; if ($cache = $this->getSourceCache($file)) { $cache->remove($this->files[$file]); } @@ -210,7 +230,7 @@ class Shared_Cache extends Cache { */ public function move($source, $target) { if ($cache = $this->getSourceCache($source)) { - $file = \OC_Share_Backend_File::getSource($target); + $file = \OC_Share_Backend_File::getSource($target, $this->storage->getMountPoint(), $this->storage->getItemType()); if ($file && isset($file['path'])) { $cache->move($this->files[$source], $file['path']); } @@ -280,16 +300,17 @@ class Shared_Cache extends Cache { $files = $this->getFolderContents($dir); // no results? if (!$files) { + // maybe it's a single shared file + $file = $this->get(''); + if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) { + $result[] = $file; + } continue; } 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)) { - // usersPath not reliable - //$file['path'] = $file['usersPath']; - $file['path'] = ltrim($dir . '/' . $file['name'], '/'); + } else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) { $result[] = $file; } } @@ -341,8 +362,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; } @@ -354,9 +373,11 @@ class Shared_Cache extends Cache { * get the size of a folder and set it in the cache * * @param string $path + * @param array $entry (optional) meta data of the folder * @return int */ - public function calculateFolderSize($path) { + public function calculateFolderSize($path, $entry = null) { + $path = ($path === false) ? '' : $path; if ($cache = $this->getSourceCache($path)) { return $cache->calculateFolderSize($this->files[$path]); } @@ -398,4 +419,49 @@ class Shared_Cache extends Cache { return false; } + /** + * get the path of a file on this storage relative to the mount point 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 + $path = $this->getShareById($id); + if (is_string($path)) { + return ltrim($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/connector/publicauth.php b/apps/files_sharing/lib/connector/publicauth.php new file mode 100644 index 0000000000..0831129ce7 --- /dev/null +++ b/apps/files_sharing/lib/connector/publicauth.php @@ -0,0 +1,71 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\Files_Sharing\Connector; + +class PublicAuth extends \Sabre_DAV_Auth_Backend_AbstractBasic { + + /** + * @var \OCP\IConfig + */ + private $config; + + private $share; + + /** + * @param \OCP\IConfig $config + */ + public function __construct($config) { + $this->config = $config; + } + + /** + * Validates a username and password + * + * This method should return true or false depending on if login + * succeeded. + * + * @param string $username + * @param string $password + * + * @return bool + */ + protected function validateUserPass($username, $password) { + $linkItem = \OCP\Share::getShareByToken($username, false); + $this->share = $linkItem; + if (!$linkItem) { + return false; + } + + // check if the share is password protected + if (isset($linkItem['share_with'])) { + if ($linkItem['share_type'] == \OCP\Share::SHARE_TYPE_LINK) { + // Check Password + $forcePortable = (CRYPT_BLOWFISH != 1); + $hasher = new \PasswordHash(8, $forcePortable); + if (!$hasher->CheckPassword($password . $this->config->getSystemValue('passwordsalt', ''), $linkItem['share_with'])) { + return false; + } else { + return true; + } + } else { + return false; + } + } else { + return true; + } + } + + /** + * @return array + */ + public function getShare() { + return $this->share; + } +} diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php new file mode 100644 index 0000000000..c7347539fc --- /dev/null +++ b/apps/files_sharing/lib/helper.php @@ -0,0 +1,183 @@ + 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; + + 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; + } + + public static function getSharesFromItem($target) { + $result = array(); + $owner = \OC\Files\Filesystem::getOwner($target); + \OC\Files\Filesystem::initMountPoints($owner); + $info = \OC\Files\Filesystem::getFileInfo($target); + $ownerView = new \OC\Files\View('/'.$owner.'/files'); + if ( $owner != \OCP\User::getUser() ) { + $path = $ownerView->getPath($info['fileid']); + } else { + $path = $target; + } + + + $ids = array(); + while ($path !== '' && $path !== '.' && $path !== '/') { + $info = $ownerView->getFileInfo($path); + if ($info instanceof \OC\Files\FileInfo) { + $ids[] = $info['fileid']; + } else { + \OCP\Util::writeLog('sharing', 'No fileinfo available for: ' . $path, \OCP\Util::WARN); + } + $path = dirname($path); + } + + if (!empty($ids)) { + + $idList = array_chunk($ids, 99, true); + + foreach ($idList as $subList) { + $statement = "SELECT `share_with`, `share_type`, `file_target` FROM `*PREFIX*share` WHERE `file_source` IN (" . implode(',', $subList) . ") AND `share_type` IN (0, 1, 2)"; + $query = \OCP\DB::prepare($statement); + $r = $query->execute(); + $result = array_merge($result, $r->fetchAll()); + } + } + + return $result; + } + + public static function getUidAndFilename($filename) { + $uid = \OC\Files\Filesystem::getOwner($filename); + \OC\Files\Filesystem::initMountPoints($uid); + if ( $uid != \OCP\User::getUser() ) { + $info = \OC\Files\Filesystem::getFileInfo($filename); + $ownerView = new \OC\Files\View('/'.$uid.'/files'); + $filename = $ownerView->getPath($info['fileid']); + } + return array($uid, $filename); + } + + /** + * @brief Format a path to be relative to the /user/files/ directory + * @param string $path the absolute path + * @return string e.g. turns '/admin/files/test.txt' into 'test.txt' + */ + public static function stripUserFilesPath($path) { + $trimmed = ltrim($path, '/'); + $split = explode('/', $trimmed); + + // it is not a file relative to data/user/files + if (count($split) < 3 || $split[1] !== 'files') { + return false; + } + + $sliced = array_slice($split, 2); + $relPath = implode('/', $sliced); + + return $relPath; + } +} diff --git a/apps/files_sharing/lib/permissions.php b/apps/files_sharing/lib/permissions.php index 31b7ac361a..c3ad63e2fd 100644 --- a/apps/files_sharing/lib/permissions.php +++ b/apps/files_sharing/lib/permissions.php @@ -31,7 +31,9 @@ class Shared_Permissions extends Permissions { */ public function get($fileId, $user) { if ($fileId == -1) { - return \OCP\PERMISSION_READ; + // if we ask for the mount point return -1 so that we can get the correct + // permissions by the path, with the root fileId we have no idea which share is meant + return -1; } $source = \OCP\Share::getItemSharedWithBySource('file', $fileId, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE, null, true); diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index ec0f368386..c0c9e0c107 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -2,8 +2,9 @@ /** * ownCloud * -* @author Michael Gapczynski -* @copyright 2012 Michael Gapczynski mtgap@owncloud.com +* @author Bjoern Schiessle, Michael Gapczynski +* @copyright 2012 Michael Gapczynski + * 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 @@ -27,6 +28,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { const FORMAT_OPENDIR = 3; const FORMAT_GET_ALL = 4; const FORMAT_PERMISSIONS = 5; + const FORMAT_TARGET_NAMES = 6; private $path; @@ -49,24 +51,37 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { return false; } + /** + * @brief create unique target + * @param string $filePath + * @param string $shareWith + * @param string $exclude + * @return string + */ public function generateTarget($filePath, $shareWith, $exclude = null) { $target = '/'.basename($filePath); - if (isset($exclude)) { - if ($pos = strrpos($target, '.')) { - $name = substr($target, 0, $pos); - $ext = substr($target, $pos); - } else { - $name = $target; - $ext = ''; - } - $i = 2; - $append = ''; - while (in_array($name.$append.$ext, $exclude)) { - $append = ' ('.$i.')'; - $i++; - } - $target = $name.$append.$ext; + + // for group shares we return the target right away + if ($shareWith === false) { + return $target; } + + \OC\Files\Filesystem::initMountPoints($shareWith); + $view = new \OC\Files\View('/' . $shareWith . '/files'); + $excludeList = \OCP\Share::getItemsSharedWithUser('file', $shareWith, self::FORMAT_TARGET_NAMES); + if (is_array($exclude)) { + $excludeList = array_merge($excludeList, $exclude); + } + + $pathinfo = pathinfo($target); + $ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : ''; + $name = $pathinfo['filename']; + $i = 2; + while ($view->file_exists($target) || in_array($target, $excludeList)) { + $target = '/' . $name . ' ('.$i.')' . $ext; + $i++; + } + return $target; } @@ -78,7 +93,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { 'path' => $items[key($items)]['path'], 'storage' => $items[key($items)]['storage'], 'permissions' => $items[key($items)]['permissions'], - 'uid_owner' => $items[key($items)]['uid_owner'] + 'uid_owner' => $items[key($items)]['uid_owner'], ); } else if ($format == self::FORMAT_GET_FOLDER_CONTENTS) { $files = array(); @@ -94,6 +109,9 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $file['mtime'] = $item['mtime']; $file['encrypted'] = $item['encrypted']; $file['etag'] = $item['etag']; + $file['uid_owner'] = $item['uid_owner']; + $file['displayname_owner'] = $item['displayname_owner']; + $storage = \OC\Files\Filesystem::getStorage('/'); $cache = $storage->getCache(); if ($item['encrypted'] or ($item['unencrypted_size'] > 0 and $cache->getMimetype($item['mimetype']) === 'httpd/unix-directory')) { @@ -105,22 +123,6 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $files[] = $file; } return $files; - } else if ($format == self::FORMAT_FILE_APP_ROOT) { - $mtime = 0; - $size = 0; - foreach ($items as $item) { - if ($item['mtime'] > $mtime) { - $mtime = $item['mtime']; - } - $size += (int)$item['size']; - } - return array( - 'fileid' => -1, - 'name' => 'Shared', - 'mtime' => $mtime, - 'mimetype' => 'httpd/unix-directory', - 'size' => $size - ); } else if ($format == self::FORMAT_OPENDIR) { $files = array(); foreach ($items as $item) { @@ -139,46 +141,60 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $filePermissions[$item['file_source']] = $item['permissions']; } return $filePermissions; + } else if ($format === self::FORMAT_TARGET_NAMES) { + $targets = array(); + foreach ($items as $item) { + $targets[] = $item['file_target']; + } + return $targets; } return array(); } - public static function getSource($target) { - if ($target == '') { - return false; - } - $target = '/'.$target; - $target = rtrim($target, '/'); - $pos = strpos($target, '/', 1); - // Get shared folder name - if ($pos !== false) { - $folder = substr($target, 0, $pos); - $source = \OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); - if ($source) { - $source['path'] = $source['path'].substr($target, strlen($folder)); + /** + * @brief resolve reshares to return the correct source item + * @param array $source + * @return array source item + */ + protected static function resolveReshares($source) { + if (isset($source['parent'])) { + $parent = $source['parent']; + while (isset($parent)) { + $query = \OC_DB::prepare('SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1); + $item = $query->execute(array($parent))->fetchRow(); + if (isset($item['parent'])) { + $parent = $item['parent']; + } else { + $fileOwner = $item['uid_owner']; + break; + } } } else { - $source = \OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + $fileOwner = $source['uid_owner']; + } + if (isset($fileOwner)) { + $source['fileOwner'] = $fileOwner; + } else { + \OCP\Util::writeLog('files_sharing', "No owner found for reshare", \OCP\Util::ERROR); + } + + return $source; + } + + public static function getSource($target, $mountPoint, $itemType) { + + if ($itemType === 'folder') { + $source = \OCP\Share::getItemSharedWith('folder', $mountPoint, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + if ($source && $target !== '') { + $source['path'] = $source['path'].'/'.$target; + } + } else { + $source = \OCP\Share::getItemSharedWith('file', $mountPoint, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); } if ($source) { - if (isset($source['parent'])) { - $parent = $source['parent']; - while (isset($parent)) { - $query = \OC_DB::prepare('SELECT `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `id` = ?', 1); - $item = $query->execute(array($parent))->fetchRow(); - if (isset($item['parent'])) { - $parent = $item['parent']; - } else { - $fileOwner = $item['uid_owner']; - break; - } - } - } else { - $fileOwner = $source['uid_owner']; - } - $source['fileOwner'] = $fileOwner; - return $source; + return self::resolveReshares($source); } + \OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, \OCP\Util::DEBUG); return false; } diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 18c8a4f42a..4733dff3d1 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -2,8 +2,9 @@ /** * ownCloud * - * @author Michael Gapczynski - * @copyright 2011 Michael Gapczynski mtgap@owncloud.com + * @author Bjoern Schiessle, Michael Gapczynski + * @copyright 2011 Michael Gapczynski + * 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 @@ -27,15 +28,27 @@ namespace OC\Files\Storage; */ class Shared extends \OC\Files\Storage\Common { - private $sharedFolder; + private $share; // the shared resource private $files = array(); public function __construct($arguments) { - $this->sharedFolder = $arguments['sharedFolder']; + $this->share = $arguments['share']; } + /** + * @breif get id of the mount point + * @return string + */ public function getId() { - return 'shared::' . $this->sharedFolder; + return 'shared::' . $this->getMountPoint(); + } + + /** + * @breif get file cache of the shared item source + * @return string + */ + public function getSourceId() { + return $this->share['file_source']; } /** @@ -48,14 +61,14 @@ class Shared extends \OC\Files\Storage\Common { if (!isset($this->files[$target])) { // Check for partial files if (pathinfo($target, PATHINFO_EXTENSION) === 'part') { - $source = \OC_Share_Backend_File::getSource(substr($target, 0, -5)); + $source = \OC_Share_Backend_File::getSource(substr($target, 0, -5), $this->getMountPoint(), $this->getItemType()); if ($source) { $source['path'] .= '.part'; // All partial files have delete permission $source['permissions'] |= \OCP\PERMISSION_DELETE; } } else { - $source = \OC_Share_Backend_File::getSource($target); + $source = \OC_Share_Backend_File::getSource($target, $this->getMountPoint(), $this->getItemType()); } $this->files[$target] = $source; } @@ -74,10 +87,11 @@ class Shared extends \OC\Files\Storage\Common { if (!isset($source['fullPath'])) { \OC\Files\Filesystem::initMountPoints($source['fileOwner']); $mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']); - if (is_array($mount)) { + if (is_array($mount) && !empty($mount)) { $this->files[$target]['fullPath'] = $mount[key($mount)]->getMountPoint() . $source['path']; } else { $this->files[$target]['fullPath'] = false; + \OCP\Util::writeLog('files_sharing', "Unable to get mount for shared storage '" . $source['storage'] . "' user '" . $source['fileOwner'] . "'", \OCP\Util::ERROR); } } return $this->files[$target]['fullPath']; @@ -117,25 +131,15 @@ class Shared extends \OC\Files\Storage\Common { } public function opendir($path) { - if ($path == '' || $path == '/') { - $files = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_Folder::FORMAT_OPENDIR); - \OC\Files\Stream\Dir::register('shared', $files); - return opendir('fakedir://shared'); - } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); - return $storage->opendir($internalPath); - } - return false; + $source = $this->getSourcePath($path); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); + return $storage->opendir($internalPath); } public function is_dir($path) { - if ($path == '' || $path == '/') { - return true; - } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); - return $storage->is_dir($internalPath); - } - return false; + $source = $this->getSourcePath($path); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); + return $storage->is_dir($internalPath); } public function is_file($path) { @@ -180,7 +184,7 @@ class Shared extends \OC\Files\Storage\Common { public function isCreatable($path) { if ($path == '') { - return false; + $path = $this->getMountPoint(); } return ($this->getPermissions($path) & \OCP\PERMISSION_CREATE); } @@ -191,21 +195,21 @@ class Shared extends \OC\Files\Storage\Common { public function isUpdatable($path) { if ($path == '') { - return false; + $path = $this->getMountPoint(); } return ($this->getPermissions($path) & \OCP\PERMISSION_UPDATE); } public function isDeletable($path) { if ($path == '') { - return true; + $path = $this->getMountPoint(); } return ($this->getPermissions($path) & \OCP\PERMISSION_DELETE); } public function isSharable($path) { if ($path == '') { - return false; + $path = $this->getMountPoint(); } return ($this->getPermissions($path) & \OCP\PERMISSION_SHARE); } @@ -221,32 +225,16 @@ class Shared extends \OC\Files\Storage\Common { } public function filemtime($path) { - if ($path == '' || $path == '/') { - $mtime = 0; - $dh = $this->opendir($path); - if (is_resource($dh)) { - while (($filename = readdir($dh)) !== false) { - $tempmtime = $this->filemtime($filename); - if ($tempmtime > $mtime) { - $mtime = $tempmtime; - } - } - } - return $mtime; - } else { - $source = $this->getSourcePath($path); - if ($source) { - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); - return $storage->filemtime($internalPath); - } - } + $source = $this->getSourcePath($path); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); + return $storage->filemtime($internalPath); } public function file_get_contents($path) { $source = $this->getSourcePath($path); if ($source) { $info = array( - 'target' => $this->sharedFolder . $path, + 'target' => $this->getMountPoint() . $path, 'source' => $source, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info); @@ -264,7 +252,7 @@ class Shared extends \OC\Files\Storage\Common { return false; } $info = array( - 'target' => $this->sharedFolder . $path, + 'target' => $this->getMountPoint() . '/' . $path, 'source' => $source, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info); @@ -277,6 +265,7 @@ class Shared extends \OC\Files\Storage\Common { public function unlink($path) { // Delete the file if DELETE permission is granted + $path = ($path === false) ? '' : $path; if ($source = $this->getSourcePath($path)) { if ($this->isDeletable($path)) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); @@ -286,23 +275,125 @@ class Shared extends \OC\Files\Storage\Common { return false; } - public function rename($path1, $path2) { - // Renaming/moving is only allowed within shared folders - $pos1 = strpos($path1, '/', 1); - $pos2 = strpos($path2, '/', 1); - if ($pos1 !== false && $pos2 !== false && ($oldSource = $this->getSourcePath($path1))) { - $newSource = $this->getSourcePath(dirname($path2)) . '/' . basename($path2); - // Within the same folder, we only need UPDATE permissions - if (dirname($path1) == dirname($path2) and $this->isUpdatable($path1)) { - list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource); - list(, $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource); - return $storage->rename($oldInternalPath, $newInternalPath); - // otherwise DELETE and CREATE permissions required - } elseif ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) { - $rootView = new \OC\Files\View(''); - return $rootView->rename($oldSource, $newSource); - } + /** + * @brief Format a path to be relative to the /user/files/ directory + * @param string $path the absolute path + * @return string e.g. turns '/admin/files/test.txt' into '/test.txt' + */ + private static function stripUserFilesPath($path) { + $trimmed = ltrim($path, '/'); + $split = explode('/', $trimmed); + + // it is not a file relative to data/user/files + if (count($split) < 3 || $split[1] !== 'files') { + \OCP\Util::writeLog('file sharing', + 'Can not strip userid and "files/" from path: ' . $path, + \OCP\Util::DEBUG); + return false; } + + // skip 'user' and 'files' + $sliced = array_slice($split, 2); + $relPath = implode('/', $sliced); + + return '/' . $relPath; + } + + /** + * @brief rename a shared folder/file + * @param string $sourcePath + * @param string $targetPath + * @return bool + */ + private function renameMountPoint($sourcePath, $targetPath) { + + // it shouldn't be possible to move a Shared storage into another one + list($targetStorage, ) = \OC\Files\Filesystem::resolvePath($targetPath); + if ($targetStorage instanceof \OC\Files\Storage\Shared) { + \OCP\Util::writeLog('file sharing', + 'It is not allowed to move one mount point into another one', + \OCP\Util::DEBUG); + return false; + } + + $relTargetPath = $this->stripUserFilesPath($targetPath); + + // if the user renames a mount point from a group share we need to create a new db entry + // for the unique name + if ($this->getShareType() === \OCP\Share::SHARE_TYPE_GROUP && $this->uniqueNameSet() === false) { + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,' + .' `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,' + .' `file_target`, `token`, `parent`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'); + $arguments = array($this->share['item_type'], $this->share['item_source'], $this->share['item_target'], + 2, \OCP\User::getUser(), $this->share['uid_owner'], $this->share['permissions'], $this->share['stime'], $this->share['file_source'], + $relTargetPath, $this->share['token'], $this->share['id']); + + } else { + // rename mount point + $query = \OC_DB::prepare( + 'Update `*PREFIX*share` + SET `file_target` = ? + WHERE `id` = ?' + ); + $arguments = array($relTargetPath, $this->getShareId()); + } + + $result = $query->execute($arguments); + + if ($result) { + // update the mount manager with the new paths + $mountManager = \OC\Files\Filesystem::getMountManager(); + $mount = $mountManager->find($sourcePath); + $mount->setMountPoint($targetPath . '/'); + $mountManager->addMount($mount); + $mountManager->removeMount($sourcePath . '/'); + $this->setUniqueName(); + $this->setMountPoint($relTargetPath); + + } else { + \OCP\Util::writeLog('file sharing', + 'Could not rename mount point for shared folder "' . $sourcePath . '" to "' . $targetPath . '"', + \OCP\Util::ERROR); + } + + return $result; + } + + + public function rename($path1, $path2) { + + $sourceMountPoint = \OC\Files\Filesystem::getMountPoint($path1); + $targetMountPoint = \OC\Files\Filesystem::getMountPoint($path2); + $relPath1 = \OCA\Files_Sharing\Helper::stripUserFilesPath($path1); + $relPath2 = \OCA\Files_Sharing\Helper::stripUserFilesPath($path2); + + // if we renamed the mount point we need to adjust the file_target in the + // database + if (\OC\Files\Filesystem::normalizePath($sourceMountPoint) === \OC\Files\Filesystem::normalizePath($path1)) { + return $this->renameMountPoint($path1, $path2); + } + + + if ( // Within the same mount point, we only need UPDATE permissions + ($sourceMountPoint === $targetMountPoint && $this->isUpdatable($sourceMountPoint)) || + // otherwise DELETE and CREATE permissions required + ($this->isDeletable($path1) && $this->isCreatable(dirname($path2)))) { + + $pathinfo = pathinfo($relPath1); + // for part files we need to ask for the owner and path from the parent directory because + // the file cache doesn't return any results for part files + if ($pathinfo['extension'] === 'part') { + list($user1, $path1) = \OCA\Files_Sharing\Helper::getUidAndFilename($pathinfo['dirname']); + $path1 = $path1 . '/' . $pathinfo['basename']; + } else { + list($user1, $path1) = \OCA\Files_Sharing\Helper::getUidAndFilename($relPath1); + } + $targetFilename = basename($relPath2); + list($user2, $path2) = \OCA\Files_Sharing\Helper::getUidAndFilename(dirname($relPath2)); + $rootView = new \OC\Files\View(''); + return $rootView->rename('/' . $user1 . '/files/' . $path1, '/' . $user2 . '/files/' . $path2 . '/' . $targetFilename); + } + return false; } @@ -343,7 +434,7 @@ class Shared extends \OC\Files\Storage\Common { } } $info = array( - 'target' => $this->sharedFolder . $path, + 'target' => $this->getMountPoint() . $path, 'source' => $source, 'mode' => $mode, ); @@ -355,9 +446,6 @@ class Shared extends \OC\Files\Storage\Common { } public function getMimeType($path) { - if ($path == '' || $path == '/') { - return 'httpd/unix-directory'; - } if ($source = $this->getSourcePath($path)) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->getMimeType($internalPath); @@ -367,13 +455,14 @@ class Shared extends \OC\Files\Storage\Common { public function free_space($path) { if ($path == '') { - return \OC\Files\SPACE_UNKNOWN; + $path = $this->getMountPoint(); } $source = $this->getSourcePath($path); if ($source) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->free_space($internalPath); } + return \OC\Files\SPACE_UNKNOWN; } public function getLocalFile($path) { @@ -393,20 +482,80 @@ class Shared extends \OC\Files\Storage\Common { } public static function setup($options) { + $shares = \OCP\Share::getItemsSharedWith('file'); if (!\OCP\User::isLoggedIn() || \OCP\User::getUser() != $options['user'] - || \OCP\Share::hasFilesSharedWith() + || $shares ) { - $user_dir = $options['user_dir']; - \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', - array('sharedFolder' => '/Shared'), - $user_dir . '/Shared/'); + foreach ($shares as $share) { + \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', + array( + 'share' => $share, + ), + $options['user_dir'] . '/' . $share['file_target']); + } } } + /** + * @brief return mount point of share, relative to data/user/files + * @return string + */ + public function getMountPoint() { + return $this->share['file_target']; + } + + /** + * @brief get share type + * @return integer can be single user share (0) group share (1), unique group share name (2) + */ + private function getShareType() { + return $this->share['share_type']; + } + + private function setMountPoint($path) { + $this->share['file_target'] = $path; + } + + /** + * @brief does the group share already has a user specific unique name + * @return bool + */ + private function uniqueNameSet() { + return (isset($this->share['unique_name']) && $this->share['unique_name']); + } + + /** + * @brief the share now uses a unique name of this user + */ + private function setUniqueName() { + $this->share['unique_name'] = true; + } + + /** + * @brief get share ID + * @return integer unique share ID + */ + private function getShareId() { + return $this->share['id']; + } + + /** + * @brief get the user who shared the file + * @return string + */ + public function getSharedFrom() { + return $this->share['uid_owner']; + } + + /** + * @brief return share type, can be "file" or "folder" + * @return string + */ + public function getItemType() { + return $this->share['item_type']; + } + public function hasUpdated($path, $time) { - if ($path == '') { - return false; - } return $this->filemtime($path) > $time; } @@ -428,7 +577,7 @@ class Shared extends \OC\Files\Storage\Common { public function getOwner($path) { if ($path == '') { - return false; + $path = $this->getMountPoint(); } $source = $this->getFile($path); if ($source) { @@ -439,7 +588,7 @@ class Shared extends \OC\Files\Storage\Common { public function getETag($path) { if ($path == '') { - return parent::getETag($path); + $path = $this->getMountPoint(); } if ($source = $this->getSourcePath($path)) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index 23ebc9fb81..249211c306 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -26,31 +26,54 @@ class Shared_Updater { // shares which can be removed from oc_share after the delete operation was successful static private $toRemove = array(); + /** + * @brief walk up the users file tree and update the etags + * @param string $user + * @param string $path + */ + static private function correctUsersFolder($user, $path) { + // $path points to the mount point which is a virtual folder, so we start with + // the parent + $path = '/files' . dirname($path); + \OC\Files\Filesystem::initMountPoints($user); + $view = new \OC\Files\View('/' . $user); + if ($view->file_exists($path)) { + while ($path !== '/') { + $etag = $view->getETag($path); + $view->putFileInfo($path, array('etag' => $etag)); + $path = dirname($path); + } + } else { + error_log("error!" . 'can not update etags on ' . $path . ' for user ' . $user); + \OCP\Util::writeLog('files_sharing', 'can not update etags on ' . $path . ' for user ' . $user, \OCP\Util::ERROR); + } + } + /** * Correct the parent folders' ETags for all users shared the file at $target * * @param string $target */ static public function correctFolders($target) { - $uid = \OCP\User::getUser(); - $uidOwner = \OC\Files\Filesystem::getOwner($target); - $info = \OC\Files\Filesystem::getFileInfo($target); - $checkedUser = array($uidOwner); + + // ignore part files + if (pathinfo($target, PATHINFO_EXTENSION) === 'part') { + return false; + } + // Correct Shared folders of other users shared with - $users = \OCP\Share::getUsersItemShared('file', $info['fileid'], $uidOwner, true); - if (!empty($users)) { - while (!empty($users)) { - $reshareUsers = array(); + $shares = \OCA\Files_Sharing\Helper::getSharesFromItem($target); + + foreach ($shares as $share) { + if ((int)$share['share_type'] === \OCP\Share::SHARE_TYPE_USER) { + self::correctUsersFolder($share['share_with'], $share['file_target']); + } elseif ((int)$share['share_type'] === \OCP\Share::SHARE_TYPE_GROUP) { + $users = \OC_Group::usersInGroup($share['share_with']); foreach ($users as $user) { - if ( !in_array($user, $checkedUser) ) { - $etag = \OC\Files\Filesystem::getETag(''); - \OCP\Config::setUserValue($user, 'files_sharing', 'etag', $etag); - // Look for reshares - $reshareUsers = array_merge($reshareUsers, \OCP\Share::getUsersItemShared('file', $info['fileid'], $user, true)); - $checkedUser[] = $user; - } + self::correctUsersFolder($user, $share['file_target']); } - $users = $reshareUsers; + } else { //unique name for group share + self::correctUsersFolder($share['share_with'], $share['file_target']); } } } @@ -108,31 +131,18 @@ class Shared_Updater { } /** - * @param array $params + * 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 shareHook($params) { - if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { - if (isset($params['uidOwner'])) { - $uidOwner = $params['uidOwner']; - } else { - $uidOwner = \OCP\User::getUser(); - } - $users = \OCP\Share::getUsersItemShared($params['itemType'], $params['fileSource'], $uidOwner, true, false); - if (!empty($users)) { - while (!empty($users)) { - $reshareUsers = array(); - foreach ($users as $user) { - if ($user !== $uidOwner) { - $etag = \OC\Files\Filesystem::getETag(''); - \OCP\Config::setUserValue($user, 'files_sharing', 'etag', $etag); - // Look for reshares - $reshareUsers = array_merge($reshareUsers, \OCP\Share::getUsersItemShared('file', $params['fileSource'], $user, true)); - } - } - $users = $reshareUsers; - } - } - } + 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/lib/watcher.php b/apps/files_sharing/lib/watcher.php index 285b1a58c6..11d3ce1cab 100644 --- a/apps/files_sharing/lib/watcher.php +++ b/apps/files_sharing/lib/watcher.php @@ -32,7 +32,7 @@ class Shared_Watcher extends Watcher { * @param string $path */ public function checkUpdate($path) { - if ($path != '' && parent::checkUpdate($path) === true) { + if (parent::checkUpdate($path) === true) { // since checkUpdate() has already updated the size of the subdirs, // only apply the update to the owner's parent dirs diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index e7a5f5024b..e17ffc4803 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -11,30 +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']; - } - return OCP\mimetype_icon($file['mimetype']); -} - if (isset($_GET['t'])) { $token = $_GET['t']; $linkItem = OCP\Share::getShareByToken($token, false); @@ -152,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']:'') @@ -169,64 +138,19 @@ if (isset($path)) { OCP\Util::addStyle('files', 'files'); OCP\Util::addStyle('files', 'upload'); + OCP\Util::addScript('files', 'filesummary'); + 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); @@ -238,19 +162,16 @@ 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('showDownloadButton', intval($allowZip)); $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path=' . urlencode($getPath)); } else { + $tmpl->assign('showDownloadButton', true); $tmpl->assign('dir', $dir); // Show file preview if viewer is available diff --git a/apps/files_sharing/publicwebdav.php b/apps/files_sharing/publicwebdav.php new file mode 100644 index 0000000000..954c3a3144 --- /dev/null +++ b/apps/files_sharing/publicwebdav.php @@ -0,0 +1,58 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +// load needed apps +$RUNTIME_APPTYPES = array('filesystem', 'authentication', 'logging'); + +OC_App::loadApps($RUNTIME_APPTYPES); + +OC_Util::obEnd(); + +// Backends +$authBackend = new OCA\Files_Sharing\Connector\PublicAuth(\OC::$server->getConfig()); +$lockBackend = new OC_Connector_Sabre_Locks(); +$requestBackend = new OC_Connector_Sabre_Request(); + +// Fire up server +$objectTree = new \OC\Connector\Sabre\ObjectTree(); +$server = new OC_Connector_Sabre_Server($objectTree); +$server->httpRequest = $requestBackend; +$server->setBaseUri($baseuri); + +// Load plugins +$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)); // Show something in the Browser, but no upload +$server->addPlugin(new OC_Connector_Sabre_FilesPlugin()); +$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin()); +$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav')); + +// wait with registering these until auth is handled and the filesystem is setup +$server->subscribeEvent('beforeMethod', function () use ($server, $objectTree, $authBackend) { + $share = $authBackend->getShare(); + $owner = $share['uid_owner']; + $fileId = $share['file_source']; + OC_Util::setupFS($owner); + $ownerView = \OC\Files\Filesystem::getView(); + $path = $ownerView->getPath($fileId); + + + $view = new \OC\Files\View($ownerView->getAbsolutePath($path)); + $rootInfo = $view->getFileInfo(''); + + // Create ownCloud Dir + $rootDir = new OC_Connector_Sabre_Directory($view, $rootInfo); + $objectTree->init($rootDir, $view); + + $server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin($view)); + $server->addPlugin(new OC_Connector_Sabre_QuotaPlugin($view)); +}, 30); // priority 30: after auth (10) and acl(20), before lock(50) and handling the request + +// And off we go! +$server->exec(); diff --git a/apps/files_sharing/templates/authenticate.php b/apps/files_sharing/templates/authenticate.php index 928be93fc9..055329ecab 100644 --- a/apps/files_sharing/templates/authenticate.php +++ b/apps/files_sharing/templates/authenticate.php @@ -8,8 +8,11 @@

- - + +

diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index 3eb84ce167..9471752b6b 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -1,3 +1,4 @@ +
@@ -9,12 +10,17 @@ -
- + +
t( 'Deleted' )); ?> - + t('Delete'))?> <?php p($l->t('Delete'))?>" /> @@ -40,6 +39,7 @@
diff --git a/apps/files_trashbin/templates/part.breadcrumb.php b/apps/files_trashbin/templates/part.breadcrumb.php deleted file mode 100644 index fdf78c190d..0000000000 --- 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/appinfo/routes.php b/apps/files_versions/appinfo/routes.php index 8d2abaa89e..80fe0e5d61 100644 --- a/apps/files_versions/appinfo/routes.php +++ b/apps/files_versions/appinfo/routes.php @@ -8,7 +8,8 @@ // Register with the capabilities API OC_API::register('get', '/cloud/capabilities', array('OCA\Files_Versions\Capabilities', 'getCapabilities'), 'files_versions', OC_API::USER_AUTH); -$this->create('core_ajax_versions_preview', '/preview.png')->action( +/** @var $this \OCP\Route\IRouter */ +$this->create('core_ajax_versions_preview', '/preview')->action( function() { require_once __DIR__ . '/../ajax/preview.php'; }); diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js index 4adf14745d..b452bc25b1 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 0000000000..31e6e72b2d --- /dev/null +++ b/apps/files_versions/l10n/ast.php @@ -0,0 +1,10 @@ + "Nun pudo revertise: %s", +"Versions" => "Versiones", +"Failed to revert {file} to revision {timestamp}." => "Fallu al revertir {file} a la revisión {timestamp}.", +"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/files_versions/l10n/ja.php b/apps/files_versions/l10n/ja.php new file mode 100644 index 0000000000..ec2601aafb --- /dev/null +++ b/apps/files_versions/l10n/ja.php @@ -0,0 +1,10 @@ + "元に戻せませんでした: %s", +"Versions" => "バージョン", +"Failed to revert {file} to revision {timestamp}." => "{file} を {timestamp} のリヴィジョンに戻すことができません。", +"More versions..." => "もっと他のバージョン...", +"No other versions available" => "利用可能な他のバージョンはありません", +"Restore" => "復元" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_versions/l10n/km.php b/apps/files_versions/l10n/km.php new file mode 100644 index 0000000000..3673d002a7 --- /dev/null +++ b/apps/files_versions/l10n/km.php @@ -0,0 +1,10 @@ + "មិន​អាច​ត្រឡប់៖ %s", +"Versions" => "កំណែ", +"Failed to revert {file} to revision {timestamp}." => "មិន​អាច​ត្រឡប់ {file} ទៅ​កំណែ​សម្រួល {timestamp} បាន​ទេ។", +"More versions..." => "កំណែ​ច្រើន​ទៀត...", +"No other versions available" => "មិន​មាន​កំណែ​ផ្សេង​ទៀត​ទេ", +"Restore" => "ស្ដារ​មក​វិញ" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_versions/l10n/nb_NO.php b/apps/files_versions/l10n/nb_NO.php index 2a0a6d8a76..4c0c8c65ba 100644 --- a/apps/files_versions/l10n/nb_NO.php +++ b/apps/files_versions/l10n/nb_NO.php @@ -1,6 +1,10 @@ "Klarte ikke å tilbakeføre: %s", "Versions" => "Versjoner", +"Failed to revert {file} to revision {timestamp}." => "Klarte ikke å tilbakeføre {file} til revisjon {timestamp}.", +"More versions..." => "Flere versjoner", +"No other versions available" => "Det finnes ingen andre versjoner", "Restore" => "Gjenopprett" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_versions/l10n/sq.php b/apps/files_versions/l10n/sq.php index 5a7a23a217..e8a0e79748 100644 --- a/apps/files_versions/l10n/sq.php +++ b/apps/files_versions/l10n/sq.php @@ -1,5 +1,10 @@ "Nuk mund të ktheje: %s", +"Versions" => "Versioni", +"Failed to revert {file} to revision {timestamp}." => "Dështoi në ktheje {skedar} të rishikimit {kohëstampe}.", +"More versions..." => "Versione m'shumë...", +"No other versions available" => "Nuk ka versione të tjera në dispozicion", "Restore" => "Rivendos" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_versions/l10n/vi.php b/apps/files_versions/l10n/vi.php index 9d72612c2a..a6f515ed0a 100644 --- a/apps/files_versions/l10n/vi.php +++ b/apps/files_versions/l10n/vi.php @@ -2,6 +2,9 @@ $TRANSLATIONS = array( "Could not revert: %s" => "Không thể khôi phục: %s", "Versions" => "Phiên bản", +"Failed to revert {file} to revision {timestamp}." => "Thất bại khi trở lại {file} khi sử đổi {timestamp}.", +"More versions..." => "Nhiều phiên bản ...", +"No other versions available" => "Không có các phiên bản khác có sẵn", "Restore" => "Khôi phục" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_versions/l10n/zh_CN.php b/apps/files_versions/l10n/zh_CN.php index 767ca1cf64..279ec2eff8 100644 --- a/apps/files_versions/l10n/zh_CN.php +++ b/apps/files_versions/l10n/zh_CN.php @@ -2,6 +2,9 @@ $TRANSLATIONS = array( "Could not revert: %s" => "无法恢复: %s", "Versions" => "版本", +"Failed to revert {file} to revision {timestamp}." => "无法恢复 {file} 到 {timestamp} 的版本。", +"More versions..." => "更多版本...", +"No other versions available" => "无其他版本可用", "Restore" => "恢复" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 2bd9c15bae..290264a90c 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -178,6 +178,7 @@ class Storage { $versionsSize = self::calculateSize($uid); } foreach ($versions as $v) { + \OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $abs_path . $v['version'])); unlink($abs_path . $v['version']); \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $abs_path . $v['version'])); $versionsSize -= $v['size']; @@ -542,8 +543,9 @@ class Storage { } foreach($toDelete as $key => $path) { - \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path)); + \OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $path)); $versionsFileview->unlink($path); + \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path)); unset($allVersions[$key]); // update array with the versions we keep \OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::DEBUG); } @@ -555,6 +557,7 @@ class Storage { $i = 0; while ($availableSpace < 0 && $i < $numOfVersions) { $version = current($allVersions); + \OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $version['path'].'.v'.$version['version'])); $versionsFileview->unlink($version['path'].'.v'.$version['version']); \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version'])); \OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::DEBUG); diff --git a/apps/user_ldap/appinfo/info.xml b/apps/user_ldap/appinfo/info.xml index 9cc908e852..e4a4375a73 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 32e2cec596..e5bec602f6 100644 --- a/apps/user_ldap/group_ldap.php +++ b/apps/user_ldap/group_ldap.php @@ -61,8 +61,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return false; } //usually, LDAP attributes are said to be case insensitive. But there are exceptions of course. - $members = $this->access->readAttribute($dn_group, - $this->access->connection->ldapGroupMemberAssocAttr); + $members = array_keys($this->_groupMembers($dn_group)); if(!$members) { $this->access->connection->writeToCache('inGroup'.$uid.':'.$gid, false); return false; @@ -89,6 +88,43 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return $isInGroup; } + /** + * @param string $dnGroup + * @param array|null &$seen + */ + private function _groupMembers($dnGroup, &$seen = null) { + if ($seen === null) { + $seen = array(); + } + $allMembers = array(); + if (array_key_exists($dnGroup, $seen)) { + // avoid loops + return array(); + } + // used extensively in cron job, caching makes sense for nested groups + $cacheKey = '_groupMembers'.$dnGroup; + if($this->access->connection->isCached($cacheKey)) { + return $this->access->connection->getFromCache($cacheKey); + } + $seen[$dnGroup] = 1; + $members = $this->access->readAttribute($dnGroup, $this->access->connection->ldapGroupMemberAssocAttr, + $this->access->connection->ldapGroupFilter); + if (is_array($members)) { + foreach ($members as $memberDN) { + $allMembers[$memberDN] = 1; + $nestedGroups = $this->access->connection->ldapNestedGroups; + if (!empty($nestedGroups)) { + $subMembers = $this->_groupMembers($memberDN, $seen); + if ($subMembers) { + $allMembers = array_merge($allMembers, $subMembers); + } + } + } + } + $this->access->connection->writeToCache($cacheKey, $allMembers); + return $allMembers; + } + /** * @brief Get all groups a user belongs to * @param $uid Name of the user @@ -124,18 +160,49 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { $uid = $userDN; } - $filter = $this->access->combineFilterWithAnd(array( - $this->access->connection->ldapGroupFilter, - $this->access->connection->ldapGroupMemberAssocAttr.'='.$uid - )); - $groups = $this->access->fetchListOfGroups($filter, - array($this->access->connection->ldapGroupDisplayName, 'dn')); + $groups = array_values($this->getGroupsByMember($uid)); $groups = array_unique($this->access->ownCloudGroupNames($groups), SORT_LOCALE_STRING); $this->access->connection->writeToCache($cacheKey, $groups); return $groups; } + /** + * @param string $dn + * @param array|null &$seen + */ + private function getGroupsByMember($dn, &$seen = null) { + if ($seen === null) { + $seen = array(); + } + $allGroups = array(); + if (array_key_exists($dn, $seen)) { + // avoid loops + return array(); + } + $seen[$dn] = true; + $filter = $this->access->combineFilterWithAnd(array( + $this->access->connection->ldapGroupFilter, + $this->access->connection->ldapGroupMemberAssocAttr.'='.$dn + )); + $groups = $this->access->fetchListOfGroups($filter, + array($this->access->connection->ldapGroupDisplayName, 'dn')); + if (is_array($groups)) { + foreach ($groups as $groupobj) { + $groupDN = $groupobj['dn']; + $allGroups[$groupDN] = $groupobj; + $nestedGroups = $this->access->connection->ldapNestedGroups; + if (!empty($nestedGroups)) { + $supergroups = $this->getGroupsByMember($groupDN, $seen); + if (is_array($supergroups) && (count($supergroups)>0)) { + $allGroups = array_merge($allGroups, $supergroups); + } + } + } + } + return $allGroups; + } + /** * @brief get a list of all users in a group * @returns array with user ids @@ -172,8 +239,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { return array(); } - $members = $this->access->readAttribute($groupDN, - $this->access->connection->ldapGroupMemberAssocAttr); + $members = array_keys($this->_groupMembers($groupDN)); if(!$members) { //in case users could not be retrieved, return empty resultset $this->access->connection->writeToCache($cachekey, array()); @@ -219,31 +285,90 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface { } /** - * @brief get a list of all display names in a group - * @returns array with display names (value) and user ids(key) + * @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 displayNamesInGroup($gid, $search, $limit, $offset) { - if(!$this->enabled) { - return array(); + public function countUsersInGroup($gid, $search = '') { + $cachekey = 'countUsersInGroup-'.$gid.'-'.$search; + if(!$this->enabled || !$this->groupExists($gid)) { + return false; } - if(!$this->groupExists($gid)) { - return array(); + $groupUsers = $this->access->connection->getFromCache($cachekey); + if(!is_null($groupUsers)) { + return $groupUsers; } - $users = $this->usersInGroup($gid, $search, $limit, $offset); - $displayNames = array(); - foreach($users as $user) { - $displayNames[$user] = \OC_User::getDisplayName($user); + + $groupDN = $this->access->groupname2dn($gid); + if(!$groupDN) { + // group couldn't be found, return empty resultset + $this->access->connection->writeToCache($cachekey, false); + return false; } - return $displayNames; + + $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 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(); } @@ -276,6 +401,51 @@ 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; + } + + /** + * @param string $group + */ public function groupMatchesFilter($group) { return (strripos($group, $this->groupSearch) !== false); } @@ -318,6 +488,6 @@ 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_COUNT_USERS & $actions); } } diff --git a/apps/user_ldap/group_proxy.php b/apps/user_ldap/group_proxy.php index 4404bd7fe3..ea94990ffe 100644 --- a/apps/user_ldap/group_proxy.php +++ b/apps/user_ldap/group_proxy.php @@ -145,19 +145,14 @@ class Group_Proxy extends lib\Proxy implements \OCP\GroupInterface { } /** - * @brief get a list of all display names in a group - * @returns array with display names (value) and user ids(key) + * @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 displayNamesInGroup($gid, $search, $limit, $offset) { - $displayNames = array(); - - foreach($this->backends as $backend) { - $backendUsers = $backend->displayNamesInGroup($gid, $search, $limit, $offset); - if (is_array($backendUsers)) { - $displayNames = array_merge($displayNames, $backendUsers); - } - } - return $displayNames; + public function countUsersInGroup($gid, $search = '') { + return $this->handleRequest( + $gid, 'countUsersInGroup', array($gid, $search)); } /** diff --git a/apps/user_ldap/js/ldapFilter.js b/apps/user_ldap/js/ldapFilter.js new file mode 100644 index 0000000000..df3bd67aec --- /dev/null +++ b/apps/user_ldap/js/ldapFilter.js @@ -0,0 +1,100 @@ +/* global LdapWizard */ + +function LdapFilter(target) { + this.locked = true; + this.target = false; + this.mode = LdapWizard.filterModeAssisted; + this.lazyRunCompose = false; + + if( target === 'User' || + target === 'Login' || + target === 'Group') { + this.target = target; + this.determineMode(); + } +} + +LdapFilter.prototype.compose = function() { + var action; + + if(this.locked) { + this.lazyRunCompose = true; + return false; + } + + if(this.target === 'User') { + action = 'getUserListFilter'; + } else if(this.target === 'Login') { + action = 'getUserLoginFilter'; + } else if(this.target === 'Group') { + action = 'getGroupFilter'; + } + + if(!$('#raw'+this.target+'FilterContainer').hasClass('invisible')) { + //Raw filter editing, i.e. user defined filter, don't compose + return; + } + + var param = 'action='+action+ + '&ldap_serverconfig_chooser='+ + encodeURIComponent($('#ldap_serverconfig_chooser').val()); + + var filter = this; + + LdapWizard.ajax(param, + function(result) { + LdapWizard.applyChanges(result); + if(filter.target === 'User') { + LdapWizard.countUsers(); + } else if(filter.target === 'Group') { + LdapWizard.countGroups(); + LdapWizard.detectGroupMemberAssoc(); + } + }, + function () { + console.log('LDAP Wizard: could not compose filter. '+ + 'Please check owncloud.log'); + } + ); +}; + +LdapFilter.prototype.determineMode = function() { + var param = 'action=get'+encodeURIComponent(this.target)+'FilterMode'+ + '&ldap_serverconfig_chooser='+ + encodeURIComponent($('#ldap_serverconfig_chooser').val()); + + var filter = this; + LdapWizard.ajax(param, + function(result) { + var property = 'ldap' + filter.target + 'FilterMode'; + filter.mode = parseInt(result.changes[property], 10); + if(filter.mode === LdapWizard.filterModeRaw && + $('#raw'+filter.target+'FilterContainer').hasClass('invisible')) { + LdapWizard['toggleRaw'+filter.target+'Filter'](); + } else if(filter.mode === LdapWizard.filterModeAssisted && + !$('#raw'+filter.target+'FilterContainer').hasClass('invisible')) { + LdapWizard['toggleRaw'+filter.target+'Filter'](); + } else { + console.log('LDAP Wizard determineMode: returned mode was »' + + filter.mode + '« of type ' + typeof filter.mode); + } + filter.unlock(); + }, + function () { + //on error case get back to default i.e. Assisted + if(!$('#raw'+filter.target+'FilterContainer').hasClass('invisible')) { + LdapWizard['toggleRaw'+filter.target+'Filter'](); + filter.mode = LdapWizard.filterModeAssisted; + } + filter.unlock(); + } + ); +}; + +LdapFilter.prototype.unlock = function() { + this.locked = false; + if(this.lazyRunCompose) { + this.lazyRunCompose = false; + this.compose(); + } +}; diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 792638f2b5..fca2dc13d1 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -14,7 +14,7 @@ var LdapConfiguration = { //deal with Checkboxes if($(elementID).is('input[type=checkbox]')) { - if(parseInt(configvalue) === 1) { + if(parseInt(configvalue, 10) === 1) { $(elementID).attr('checked', 'checked'); } else { $(elementID).removeAttr('checked'); @@ -145,6 +145,9 @@ var LdapWizard = { spinner: '', filterModeAssisted: 0, filterModeRaw: 1, + userFilter: false, + loginFilter: false, + groupFilter: false, ajax: function(param, fnOnSuccess, fnOnError) { $.post( @@ -276,41 +279,6 @@ var LdapWizard = { } }, - composeFilter: function(type) { - subject = type.charAt(0).toUpperCase() + type.substr(1); - if(!$('#raw'+subject+'FilterContainer').hasClass('invisible')) { - //Raw filter editing, i.e. user defined filter, don't compose - return; - } - - if(type == 'user') { - action = 'getUserListFilter'; - } else if(type == 'login') { - action = 'getUserLoginFilter'; - } else if(type == 'group') { - action = 'getGroupFilter'; - } - - param = 'action='+action+ - '&ldap_serverconfig_chooser='+ - encodeURIComponent($('#ldap_serverconfig_chooser').val()); - - LdapWizard.ajax(param, - function(result) { - LdapWizard.applyChanges(result); - if(type == 'user') { - LdapWizard.countUsers(); - } else if(type == 'group') { - LdapWizard.countGroups(); - LdapWizard.detectGroupMemberAssoc(); - } - }, - function (result) { - // error handling - } - ); - }, - controlBack: function() { curTabIndex = $('#ldapSettings').tabs('option', 'active'); if(curTabIndex == 0) { @@ -510,7 +478,7 @@ var LdapWizard = { }, functionalityCheck: function() { - //criterias to enable the connection: + //criteria to enable the connection: // - host, port, basedn, user filter, login filter host = $('#ldap_host').val(); port = $('#ldap_port').val(); @@ -560,7 +528,7 @@ var LdapWizard = { }, initGroupFilter: function() { - LdapWizard.regardFilterMode('Group'); + LdapWizard.groupFilter = new LdapFilter('Group'); LdapWizard.findObjectClasses('ldap_groupfilter_objectclass', 'Group'); LdapWizard.findAvailableGroups('ldap_groupfilter_groups', 'Groups'); LdapWizard.countGroups(); @@ -569,13 +537,13 @@ var LdapWizard = { /** init login filter tab section **/ initLoginFilter: function() { - LdapWizard.regardFilterMode('Login'); + LdapWizard.loginFilter = new LdapFilter('Login'); LdapWizard.findAttributes(); }, postInitLoginFilter: function() { if($('#rawLoginFilterContainer').hasClass('invisible')) { - LdapWizard.composeFilter('login'); + LdapWizard.loginFilter.compose(); } }, @@ -588,7 +556,7 @@ var LdapWizard = { noneSelectedText: caption, click: function(event, ui) { LdapWizard.saveMultiSelect(id, - $('#'+id).multiselect("getChecked")); + $('#'+id).multiselect("getChecked")); } }); }, @@ -601,15 +569,15 @@ var LdapWizard = { initUserFilter: function() { LdapWizard.userFilterObjectClassesHasRun = false; LdapWizard.userFilterAvailableGroupsHasRun = false; - LdapWizard.regardFilterMode('User'); + LdapWizard.userFilter = new LdapFilter('User'); LdapWizard.findObjectClasses('ldap_userfilter_objectclass', 'User'); LdapWizard.findAvailableGroups('ldap_userfilter_groups', 'Users'); }, postInitUserFilter: function() { - if(LdapWizard.userFilterObjectClassesHasRun - && LdapWizard.userFilterAvailableGroupsHasRun) { - LdapWizard.composeFilter('user'); + if(LdapWizard.userFilterObjectClassesHasRun && + LdapWizard.userFilterAvailableGroupsHasRun) { + LdapWizard.userFilter.compose(); LdapWizard.countUsers(); } }, @@ -658,7 +626,7 @@ var LdapWizard = { if(triggerObj.id == 'ldap_loginfilter_username' || triggerObj.id == 'ldap_loginfilter_email') { - LdapWizard.composeFilter('login'); + LdapWizard.loginFilter.compose(); } if($('#ldapSettings').tabs('option', 'active') == 0) { @@ -667,32 +635,6 @@ var LdapWizard = { } }, - regardFilterMode: function(subject) { - param = 'action=get'+encodeURIComponent(subject)+'FilterMode'+ - '&ldap_serverconfig_chooser='+ - encodeURIComponent($('#ldap_serverconfig_chooser').val()); - - LdapWizard.ajax(param, - function(result) { - property = 'ldap' + subject + 'FilterMode'; - mode = result.changes[property]; - if(mode == LdapWizard.filterModeRaw - && $('#raw'+subject+'FilterContainer').hasClass('invisible')) { - LdapWizard['toggleRaw'+subject+'Filter'](); - } else if(mode == LdapWizard.filterModeAssisted - && !$('#raw'+subject+'FilterContainer').hasClass('invisible')) { - LdapWizard['toggleRaw'+subject+'Filter'](); - } - }, - function (result) { - //on error case get back to default i.e. Assisted - if(!$('#raw'+subject+'FilterContainer').hasClass('invisible')) { - LdapWizard['toggleRaw'+subject+'Filter'](); - } - } - ); - }, - save: function(inputObj) { if(LdapWizard.blacklistRemove(inputObj.id)) { return; @@ -714,15 +656,15 @@ var LdapWizard = { LdapWizard._save($('#'+originalObj)[0], $.trim(values)); if(originalObj == 'ldap_userfilter_objectclass' || originalObj == 'ldap_userfilter_groups') { - LdapWizard.composeFilter('user'); + LdapWizard.userFilter.compose(); //when user filter is changed afterwards, login filter needs to //be adjusted, too - LdapWizard.composeFilter('login'); + LdapWizard.loginFilter.compose(); } else if(originalObj == 'ldap_loginfilter_attributes') { - LdapWizard.composeFilter('login'); + LdapWizard.loginFilter.compose(); } else if(originalObj == 'ldap_groupfilter_objectclass' || originalObj == 'ldap_groupfilter_groups') { - LdapWizard.composeFilter('group'); + LdapWizard.groupFilter.compose(); } }, @@ -778,10 +720,10 @@ var LdapWizard = { LdapWizard._save({ id: modeKey }, LdapWizard.filterModeAssisted); if(moc.indexOf('user') >= 0) { LdapWizard.blacklistRemove('ldap_userlist_filter'); - LdapWizard.composeFilter('user'); + LdapWizard.userFilter.compose(); } else { LdapWizard.blacklistRemove('ldap_group_filter'); - LdapWizard.composeFilter('group'); + LdapWizard.groupFilter.compose(); } } }, @@ -815,7 +757,7 @@ var LdapWizard = { $('#ldap_loginfilter_username').prop('disabled', property); LdapWizard._save({ id: 'ldapLoginFilterMode' }, mode); if(action == 'enable') { - LdapWizard.composeFilter('login'); + LdapWizard.loginFilter.compose(); } }, diff --git a/apps/user_ldap/l10n/af_ZA.php b/apps/user_ldap/l10n/af_ZA.php index 130e471e0e..483a30b8e4 100644 --- a/apps/user_ldap/l10n/af_ZA.php +++ b/apps/user_ldap/l10n/af_ZA.php @@ -3,6 +3,7 @@ $TRANSLATIONS = array( "_%s group found_::_%s groups found_" => array("",""), "_%s user found_::_%s users found_" => array("",""), "Help" => "Hulp", -"Password" => "Wagwoord" +"Password" => "Wagwoord", +"Continue" => "Gaan voort" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/am_ET.php b/apps/user_ldap/l10n/am_ET.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/am_ET.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/ar.php b/apps/user_ldap/l10n/ar.php index 2b0cbbd75a..a2152dde85 100644 --- a/apps/user_ldap/l10n/ar.php +++ b/apps/user_ldap/l10n/ar.php @@ -1,6 +1,9 @@ "تعذر حذف ملف إعدادات الخادم", +"The configuration is valid and the connection could be established!" => "الإعدادت صحيحة", "Deletion failed" => "فشل الحذف", +"Success" => "نجاح", "Error" => "خطأ", "Select groups" => "إختر مجموعة", "_%s group found_::_%s groups found_" => array("","","","","",""), @@ -8,7 +11,9 @@ $TRANSLATIONS = array( "Save" => "حفظ", "Help" => "المساعدة", "Host" => "المضيف", +"Port" => "المنفذ", "Password" => "كلمة المرور", -"Back" => "رجوع" +"Back" => "رجوع", +"Email Field" => "خانة البريد الإلكتروني" ); $PLURAL_FORMS = "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"; diff --git a/apps/user_ldap/l10n/ast.php b/apps/user_ldap/l10n/ast.php new file mode 100644 index 0000000000..ceda5a9326 --- /dev/null +++ b/apps/user_ldap/l10n/ast.php @@ -0,0 +1,44 @@ + "Fallu al desaniciar la configuración del sevidor", +"The configuration is valid and the connection could be established!" => "¡La configuración ye válida y pudo afitase la conexón!", +"The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "La configuración ye válida, pero falló'l vínculu. Por favor, comprueba la configuración y les credenciales nel servidor.", +"The configuration is invalid. Please have a look at the logs for further details." => "La configuración nun ye válida. Por favor, écha-y un güeyu a los rexistros pa más detalles.", +"No action specified" => "Nun s'especificó l'aición", +"No configuration specified" => "Nun s'especificó la configuración", +"No data specified" => "Nun s'especificaron los datos", +" Could not set configuration %s" => "Nun pudo afitase la configuración %s", +"Deletion failed" => "Falló'l borráu", +"Keep settings?" => "¿Caltener los axustes?", +"Cannot add server configuration" => "Nun pue amestase la configuración del sirvidor", +"Success" => "Con ésitu", +"Error" => "Fallu", +"Configuration incorrect" => "Configuración incorreuta", +"Configuration incomplete" => "Configuración incompleta", +"Select groups" => "Esbillar grupos", +"Select attributes" => "Esbillar atributos", +"_%s group found_::_%s groups found_" => array("%s grupu alcontráu","%s grupos alcontraos"), +"_%s user found_::_%s users found_" => array("%s usuariu alcontráu","%s usuarios alcontraos"), +"Could not find the desired feature" => "Nun pudo alcontrase la carauterística deseyada", +"Save" => "Guardar", +"groups found" => "grupos alcontraos", +"Users login with this attribute:" => "Aniciu de sesión d'usuarios con esti atributu:", +"LDAP Username:" => "Nome d'usuariu LDAP", +"Other Attributes:" => "Otros atributos:", +"Add Server Configuration" => "Amestar configuración del sirvidor", +"Host" => "Equipu", +"Port" => "Puertu", +"Password" => "Contraseña", +"For anonymous access, leave DN and Password empty." => "Pa un accesu anónimu, dexar el DN y la contraseña baleros.", +"users found" => "usuarios alcontraos", +"Continue" => "Continuar", +"Connection Settings" => "Axustes de conexón", +"Configuration Active" => "Configuración activa", +"When unchecked, this configuration will be skipped." => "Cuando nun tea conseñáu, saltaráse esta configuración.", +"Disable Main Server" => "Deshabilitar sirvidor principal", +"Turn off SSL certificate validation." => "Apagar la validación del certificáu SSL.", +"Directory Settings" => "Axustes del direutoriu", +"in bytes" => "en bytes", +"Internal Username" => "Nome d'usuariu internu" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/az.php b/apps/user_ldap/l10n/az.php index bba52d53a1..3a1e002311 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 0b43a27df9..90f7b572a9 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 2ebaa7d7a5..c8542586f8 100644 --- a/apps/user_ldap/l10n/ca.php +++ b/apps/user_ldap/l10n/ca.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Desa", "Test Configuration" => "Comprovació de la configuració", "Help" => "Ajuda", -"Limit the access to %s to groups meeting this criteria:" => "Limita l'accés a %s grups que compleixin amb el criteri:", +"Groups meeting these criteria are available in %s:" => "Els grups que compleixen aquests criteris estan disponibles a %s:", "only those object classes:" => "només aquestes classes d'objecte:", "only from those groups:" => "només d'aquests grups", "Edit raw filter instead" => "Edita filtre raw", "Raw LDAP filter" => "Filtre raw LDAP", "The filter specifies which LDAP groups shall have access to the %s instance." => "El filtre especifica quins grups LDAP haurien de tenir accés a la instància %s.", "groups found" => "grups trobats", -"What attribute shall be used as login name:" => "Quin atribut s'hauria d'utilitzar com a nom per a l'acreditació:", +"Users login with this attribute:" => "Usuaris acreditats amb aquest atribut:", "LDAP Username:" => "Nom d'usuari LDAP:", "LDAP Email Address:" => "Adreça de correu electrònic LDAP:", "Other Attributes:" => "Altres atributs:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Per un accés anònim, deixeu la DN i la contrasenya en blanc.", "One Base DN per line" => "Una DN Base per línia", "You can specify Base DN for users and groups in the Advanced tab" => "Podeu especificar DN Base per usuaris i grups a la pestanya Avançat", -"Limit the access to %s to users meeting this criteria:" => "Limita l'accés a %s usuaris que compleixin amb el criteri:", +"Limit %s access to users meeting these criteria:" => "Limita l'accés a %s usuaris que compleixin amb aquest criteri:", "The filter specifies which LDAP users shall have access to the %s instance." => "El filtre especifica quins usuaris LDAP haurien de tenir accés a la instància %s", "users found" => "usuaris trobats", "Back" => "Enrera", @@ -70,7 +70,7 @@ $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)", +"Case insensitive 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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Una DN Base de Grup per línia", "Group Search Attributes" => "Atributs de cerca de grup", "Group-Member association" => "Associació membres-grup", +"Nested Groups" => "Grups imbricats", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Quan està activat, els grups que contenen grups estan permesos. (Només funciona si l'atribut del grup membre conté DNs.)", +"Paging chunksize" => "Mida de la pàgina", +"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.)" => "Mida usada per cerques LDAP paginades que podrien retornar respostes de volcat com enumeració d'usuari o grup. (Establint-ho a 0 desactiva les cerques LDAP paginades en aquestes situacions.)", "Special Attributes" => "Atributs especials", "Quota Field" => "Camp de quota", "Quota Default" => "Quota per defecte", diff --git a/apps/user_ldap/l10n/cs_CZ.php b/apps/user_ldap/l10n/cs_CZ.php index 6bcf364ab3..b7dfa5a4c4 100644 --- a/apps/user_ldap/l10n/cs_CZ.php +++ b/apps/user_ldap/l10n/cs_CZ.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Uložit", "Test Configuration" => "Vyzkoušet nastavení", "Help" => "Nápověda", -"Limit the access to %s to groups meeting this criteria:" => "Omezit přístup k %s skupinám uživatelů splňujícím tyto podmínky:", +"Groups meeting these criteria are available in %s:" => "Skupiny splňující tyto podmínky jsou k dispozici v %s:", "only those object classes:" => "pouze tyto objektové třídy:", "only from those groups:" => "pouze z těchto skupin:", "Edit raw filter instead" => "Edituj filtr přímo", "Raw LDAP filter" => "Původní filtr LDAP", "The filter specifies which LDAP groups shall have access to the %s instance." => "Filtr určuje, kteří uživatelé LDAP mají mít přístup k instanci %s.", "groups found" => "nalezené skupiny", -"What attribute shall be used as login name:" => "Který atribut má být použit jako přihlašovací jméno:", +"Users login with this attribute:" => "Uživatelé se přihlašují s tímto atributem:", "LDAP Username:" => "LDAP uživatelské jméno:", "LDAP Email Address:" => "LDAP e-mailová adresa:", "Other Attributes:" => "Další atributy:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Pro anonymní přístup ponechte údaje DN and heslo prázdné.", "One Base DN per line" => "Jedna základní DN na řádku", "You can specify Base DN for users and groups in the Advanced tab" => "V rozšířeném nastavení můžete určit základní DN pro uživatele a skupiny", -"Limit the access to %s to users meeting this criteria:" => "Omezit přístup k %s uživatelům splňujícím tyto podmínky:", +"Limit %s access to users meeting these criteria:" => "Omezit přístup %s uživatelům splňujícím tyto podmínky:", "The filter specifies which LDAP users shall have access to the %s instance." => "Filtr určuje, kteří uživatelé LDAP mají mít přístup k instanci %s.", "users found" => "nalezení uživatelé", "Back" => "Zpět", @@ -70,7 +70,7 @@ $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)", +"Case insensitive 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", @@ -88,6 +88,8 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Jedna skupinová základní DN na řádku", "Group Search Attributes" => "Atributy vyhledávání skupin", "Group-Member association" => "Asociace člena skupiny", +"Nested Groups" => "Vnořené skupiny", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Pokud zapnuto, je možno používat skupiny, které obsahují jiné skupiny. (Funguje pouze pokud atribut člena skupiny obsahuje DN.)", "Special Attributes" => "Speciální atributy", "Quota Field" => "Pole pro kvótu", "Quota Default" => "Výchozí kvóta", diff --git a/apps/user_ldap/l10n/da.php b/apps/user_ldap/l10n/da.php index e375598c9b..8264a18116 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 0c80ecfa85..4333652073 100644 --- a/apps/user_ldap/l10n/de.php +++ b/apps/user_ldap/l10n/de.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Speichern", "Test Configuration" => "Testkonfiguration", "Help" => "Hilfe", -"Limit the access to %s to groups meeting this criteria:" => "Beschränke den Zugriff auf %s auf Gruppen, die die folgenden Kriterien erfüllen:", +"Groups meeting these criteria are available in %s:" => "Gruppen-Versammlungen mit diesen Kriterien sind verfügbar in %s:", "only those object classes:" => "Nur diese Objekt-Klassen:", "only from those groups:" => "Nur von diesen Gruppen:", "Edit raw filter instead" => "Original-Filter stattdessen bearbeiten", "Raw LDAP filter" => "Original LDAP-Filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "Der Filter definiert welche LDAP-Gruppen Zugriff auf die %s Instanz haben sollen.", "groups found" => "Gruppen gefunden", -"What attribute shall be used as login name:" => "Welches Attribut soll als Login-Name verwendet werden:", +"Users login with this attribute:" => "Nutzeranmeldung mit diesem Merkmal:", "LDAP Username:" => "LDAP-Benutzername:", "LDAP Email Address:" => "LDAP E-Mail-Adresse:", "Other Attributes:" => "Andere Attribute:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Lasse die Felder DN und Passwort für anonymen Zugang leer.", "One Base DN per line" => "Ein Basis-DN pro Zeile", "You can specify Base DN for users and groups in the Advanced tab" => "Du kannst Basis-DN für Benutzer und Gruppen in dem \"Erweitert\"-Reiter konfigurieren", -"Limit the access to %s to users meeting this criteria:" => "Beschränke den Zugriff auf %s auf Benutzer, die die folgenden Kriterien erfüllen:", +"Limit %s access to users meeting these criteria:" => "Beschränken Sie den %s Zugriff auf die Benutzer-Sitzungen durch folgende Kriterien:", "The filter specifies which LDAP users shall have access to the %s instance." => "Der Filter definiert welche LDAP-Benutzer Zugriff auf die %s Instanz haben sollen.", "users found" => "Benutzer gefunden", "Back" => "Zurück", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Ein Gruppen Basis-DN pro Zeile", "Group Search Attributes" => "Gruppensucheigenschaften", "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_AT.php b/apps/user_ldap/l10n/de_AT.php index 3a1e002311..a4e97dfcad 100644 --- a/apps/user_ldap/l10n/de_AT.php +++ b/apps/user_ldap/l10n/de_AT.php @@ -1,6 +1,9 @@ "Löschen fehlgeschlagen", "_%s group found_::_%s groups found_" => array("",""), -"_%s user found_::_%s users found_" => array("","") +"_%s user found_::_%s users found_" => array("",""), +"Save" => "Speichern", +"Password" => "Passwort" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/de_CH.php b/apps/user_ldap/l10n/de_CH.php index 5f8e2907f0..f60d425a2e 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 168f1fe059..21c149d1a1 100644 --- a/apps/user_ldap/l10n/de_DE.php +++ b/apps/user_ldap/l10n/de_DE.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Speichern", "Test Configuration" => "Testkonfiguration", "Help" => "Hilfe", -"Limit the access to %s to groups meeting this criteria:" => "Beschränke den Zugriff auf %s auf Gruppen, die die folgenden Kriterien erfüllen:", +"Groups meeting these criteria are available in %s:" => "Gruppen-Versammlungen mit diesen Kriterien sind verfügbar in %s:", "only those object classes:" => "Nur diese Objekt-Klassen:", "only from those groups:" => "Nur von diesen Gruppen:", "Edit raw filter instead" => "Original-Filter stattdessen bearbeiten", "Raw LDAP filter" => "Original LDAP-Filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "Der Filter definiert welche LDAP-Gruppen Zugriff auf die %s Instanz haben sollen.", "groups found" => "Gruppen gefunden", -"What attribute shall be used as login name:" => "Welches Attribut soll als Login-Name verwendet werden:", +"Users login with this attribute:" => "Nutzeranmeldung mit diesem Merkmal:", "LDAP Username:" => "LDAP-Benutzername:", "LDAP Email Address:" => "LDAP E-Mail-Adresse:", "Other Attributes:" => "Andere Attribute:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Lassen Sie die Felder DN und Passwort für einen anonymen Zugang leer.", "One Base DN per line" => "Ein Basis-DN pro Zeile", "You can specify Base DN for users and groups in the Advanced tab" => "Sie können Basis-DN für Benutzer und Gruppen in dem \"Erweitert\"-Reiter konfigurieren", -"Limit the access to %s to users meeting this criteria:" => "Beschränke den Zugriff auf %s auf Benutzer, die die folgenden Kriterien erfüllen:", +"Limit %s access to users meeting these criteria:" => "Beschränken Sie den %s Zugriff auf die Benutzer-Sitzungen durch folgende Kriterien:", "The filter specifies which LDAP users shall have access to the %s instance." => "Der Filter definiert welche LDAP-Benutzer Zugriff auf die %s Instanz haben sollen.", "users found" => "Benutzer gefunden", "Back" => "Zurück", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Ein Gruppen Basis-DN pro Zeile", "Group Search Attributes" => "Gruppensucheigenschaften", "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 8369dff489..cfc5286a40 100644 --- a/apps/user_ldap/l10n/el.php +++ b/apps/user_ldap/l10n/el.php @@ -8,6 +8,7 @@ $TRANSLATIONS = array( "No action specified" => "Καμμία εντολή δεν προσδιορίστηκε", "No configuration specified" => "Καμμία διαμόρφωση δεν προσδιορίστηκε", "No data specified" => "Δεν προσδιορίστηκαν δεδομένα", +" Could not set configuration %s" => "Αδυναμία ρύθμισης %s", "Deletion failed" => "Η διαγραφή απέτυχε", "Take over settings from recent server configuration?" => "Πάρτε πάνω από τις πρόσφατες ρυθμίσεις διαμόρφωσης του διακομιστή?", "Keep settings?" => "Διατήρηση ρυθμίσεων;", @@ -32,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Αποθήκευση", "Test Configuration" => "Δοκιμαστικες ρυθμισεις", "Help" => "Βοήθεια", -"Limit the access to %s to groups meeting this criteria:" => "Περιορισμός πρόσβασης %s σε ομάδες που ταιριάζουν αυτά τα κριτήρια:", +"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" => "ομάδες βρέθηκαν", -"What attribute shall be used as login name:" => "Ποια ιδιότητα θα χρησιμοποιηθεί ως όνομα σύνδεσης:", +"Users login with this attribute:" => "Οι χρήστες εισέρχονται με αυτό το χαρακτηριστικό:", "LDAP Username:" => "Όνομα χρήστη LDAP:", "LDAP Email Address:" => "Διεύθυνση ηλ. ταχυδρομείου LDAP:", "Other Attributes:" => "Άλλες Ιδιότητες:", @@ -54,7 +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 the access to %s to users meeting this criteria:" => "Περιορισμός πρόσβασης %s σε χρήστες που ταιριάζουν αυτά τα κριτήρια:", +"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" => "Επιστροφή", @@ -68,7 +69,7 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Δώστε μια προαιρετική εφεδρική υποδοχή. Πρέπει να είναι ένα αντίγραφο του κύριου LDAP / AD διακομιστη.", "Backup (Replica) Port" => "Δημιουργία αντιγράφων ασφαλείας (Replica) Υποδοχη", "Disable Main Server" => "Απενεργοποιηση του κεντρικου διακομιστη", -"Case insensitve LDAP server (Windows)" => "LDAP server (Windows) με διάκριση πεζών-ΚΕΦΑΛΑΙΩΝ", +"Only connect to the replica server." => "Σύνδεση μόνο με το διακομιστή-αντίγραφο.", "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", @@ -86,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 b83229d5a5..cb0ac1a549 100644 --- a/apps/user_ldap/l10n/en_GB.php +++ b/apps/user_ldap/l10n/en_GB.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Save", "Test Configuration" => "Test Configuration", "Help" => "Help", -"Limit the access to %s to groups meeting this criteria:" => "Limit the access to %s to groups meeting this criteria:", +"Groups meeting these criteria are available in %s:" => "Groups meeting these criteria are available in %s:", "only those object classes:" => "only those object classes:", "only from those groups:" => "only from those groups:", "Edit raw filter instead" => "Edit raw filter instead", "Raw LDAP filter" => "Raw LDAP filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "The filter specifies which LDAP groups shall have access to the %s instance.", "groups found" => "groups found", -"What attribute shall be used as login name:" => "What attribute should be used as login name:", +"Users login with this attribute:" => "Users login with this attribute:", "LDAP Username:" => "LDAP Username:", "LDAP Email Address:" => "LDAP Email Address:", "Other Attributes:" => "Other Attributes:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "For anonymous access, leave DN and Password empty.", "One Base DN per line" => "One Base DN per line", "You can specify Base DN for users and groups in the Advanced tab" => "You can specify Base DN for users and groups in the Advanced tab", -"Limit the access to %s to users meeting this criteria:" => "Limit the access to %s to users meeting this criteria:", +"Limit %s access to users meeting these criteria:" => "Limit %s access to users meeting these criteria:", "The filter specifies which LDAP users shall have access to the %s instance." => "The filter specifies which LDAP users shall have access to the %s instance.", "users found" => "users found", "Back" => "Back", @@ -70,7 +70,7 @@ $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)", +"Case insensitive LDAP server (Windows)" => "Case insensitive 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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "One Group Base DN per line", "Group Search Attributes" => "Group Search Attributes", "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/en_NZ.php b/apps/user_ldap/l10n/en_NZ.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/en_NZ.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/eo.php b/apps/user_ldap/l10n/eo.php index 0cae524bcc..74928899c8 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 3348003e3e..bb1c9acb2a 100644 --- a/apps/user_ldap/l10n/es.php +++ b/apps/user_ldap/l10n/es.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "mappings cleared" => "Asignaciones borradas", "Success" => "Éxito", "Error" => "Error", -"Configuration OK" => "Configuración OK", +"Configuration OK" => "Configuración Correcta", "Configuration incorrect" => "Configuración Incorrecta", "Configuration incomplete" => "Configuración incompleta", "Select groups" => "Seleccionar grupos", @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Guardar", "Test Configuration" => "Configuración de prueba", "Help" => "Ayuda", -"Limit the access to %s to groups meeting this criteria:" => "Limitar el acceso a %s a los grupos que cumplan este criterio:", +"Groups meeting these criteria are available in %s:" => "Los grupos que cumplen estos criterios están disponibles en %s:", "only those object classes:" => "solamente de estas clases de objeto:", "only from those groups:" => "solamente de estos grupos:", "Edit raw filter instead" => "Editar el filtro en bruto en su lugar", "Raw LDAP filter" => "Filtro LDAP en bruto", "The filter specifies which LDAP groups shall have access to the %s instance." => "El filtro especifica que grupos LDAP tendrán acceso a %s.", "groups found" => "grupos encontrados", -"What attribute shall be used as login name:" => "Que atributo debe ser usado como login:", +"Users login with this attribute:" => "Los usuarios inician sesión con este atributo:", "LDAP Username:" => "Nombre de usuario LDAP:", "LDAP Email Address:" => "Dirección e-mail LDAP:", "Other Attributes:" => "Otros atributos:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Para acceso anónimo, deje DN y contraseña vacíos.", "One Base DN per line" => "Un DN Base por línea", "You can specify Base DN for users and groups in the Advanced tab" => "Puede especificar el DN base para usuarios y grupos en la pestaña Avanzado", -"Limit the access to %s to users meeting this criteria:" => "Limitar el acceso a %s a los usuarios que cumplan el siguiente criterio:", +"Limit %s access to users meeting these criteria:" => "Limitar el acceso a %s a los usuarios que cumplan estos criterios:", "The filter specifies which LDAP users shall have access to the %s instance." => "El filtro especifica que usuarios LDAP pueden tener acceso a %s.", "users found" => "usuarios encontrados", "Back" => "Atrás", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Un DN Base de Grupo por línea", "Group Search Attributes" => "Atributos de busqueda de grupo", "Group-Member association" => "Asociación Grupo-Miembro", +"Nested Groups" => "Grupos anidados", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Cuando se active, se permitirán grupos que contenga otros grupos (solo funciona si el atributo de miembro de grupo contiene DNs).", +"Paging chunksize" => "Tamaño de los fragmentos de paginación", +"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 de los fragmentos usado para búsquedas LDAP paginadas que pueden devolver resultados voluminosos, como enumeración de usuarios o de grupos. (Si se establece en 0, se deshabilitan las búsquedas LDAP paginadas en esas situaciones.)", "Special Attributes" => "Atributos especiales", "Quota Field" => "Cuota", "Quota Default" => "Cuota por defecto", diff --git a/apps/user_ldap/l10n/es_AR.php b/apps/user_ldap/l10n/es_AR.php index 3a8f42e2c9..4a8047c6d9 100644 --- a/apps/user_ldap/l10n/es_AR.php +++ b/apps/user_ldap/l10n/es_AR.php @@ -4,6 +4,11 @@ $TRANSLATIONS = array( "Failed to delete the server configuration" => "Fallo al borrar la configuración del servidor", "The configuration is valid and the connection could be established!" => "La configuración es válida y la conexión pudo ser establecida.", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "La configuración es válida, pero el enlace falló. Por favor, comprobá la configuración del servidor y las credenciales.", +"The configuration is invalid. Please have a look at the logs for further details." => "La configuración es inválida. Por favor, verifique los logs para más detalles.", +"No action specified" => "No se ha especificado una acción", +"No configuration specified" => "No se ha especificado una configuración", +"No data specified" => "No se ha especificado datos", +" Could not set configuration %s" => "No se pudo asignar la configuración %s", "Deletion failed" => "Error al borrar", "Take over settings from recent server configuration?" => "Tomar los valores de la anterior configuración de servidor?", "Keep settings?" => "¿Mantener preferencias?", @@ -11,16 +16,34 @@ $TRANSLATIONS = array( "mappings cleared" => "Asignaciones borradas", "Success" => "Éxito", "Error" => "Error", +"Configuration OK" => "Configuración válida", +"Configuration incorrect" => "Configuración incorrecta", +"Configuration incomplete" => "Configuración incompleta", "Select groups" => "Seleccionar grupos", +"Select object classes" => "Seleccionar las clases de objetos", +"Select attributes" => "Seleccionar atributos", "Connection test succeeded" => "El este de conexión ha sido completado satisfactoriamente", "Connection test failed" => "Falló es test de conexión", "Do you really want to delete the current Server Configuration?" => "¿Realmente desea borrar la configuración actual del servidor?", "Confirm Deletion" => "Confirmar borrado", -"_%s group found_::_%s groups found_" => array("",""), -"_%s user found_::_%s users found_" => array("",""), +"_%s group found_::_%s groups found_" => array("%s grupo encontrado","%s grupos encontrados"), +"_%s user found_::_%s users found_" => array("%s usuario encontrado","%s usuarios encontrados"), +"Invalid Host" => "Host inválido", +"Could not find the desired feature" => "No se pudo encontrar la característica deseada", "Save" => "Guardar", "Test Configuration" => "Probar configuración", "Help" => "Ayuda", +"Groups meeting these criteria are available in %s:" => "Los grupos que cumplen con estos criterios están disponibles en %s:", +"only those object classes:" => "solo estos objetos de clases:", +"only from those groups:" => "solo provenientes de estos grupos:", +"Edit raw filter instead" => "Editar filtro en bruto", +"Raw LDAP filter" => "Filtro LDAP en bruto", +"The filter specifies which LDAP groups shall have access to the %s instance." => "El filtro especifica qué grupos LDAP deben tener acceso a la instancia %s.", +"groups found" => "grupos encontrados", +"Users login with this attribute:" => "Los usuarios inician sesión con este atributo:", +"LDAP Username:" => "Nombre de usuario LDAP:", +"LDAP Email Address:" => "Correo electrónico LDAP:", +"Other Attributes:" => "Otros atributos:", "Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "Define el filtro a aplicar cuando se intenta ingresar. %%uid remplaza el nombre de usuario en el proceso de identificación. Por ejemplo: \"uid=%%uid\"", "Add Server Configuration" => "Añadir Configuración del Servidor", "Host" => "Servidor", @@ -32,7 +55,11 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Para acceso anónimo, dejá DN y contraseña vacíos.", "One Base DN per line" => "Una DN base por línea", "You can specify Base DN for users and groups in the Advanced tab" => "Podés especificar el DN base para usuarios y grupos en la pestaña \"Avanzado\"", +"Limit %s access to users meeting these criteria:" => "Limitar acceso %s a los usuarios que cumplen con este criterio:", +"The filter specifies which LDAP users shall have access to the %s instance." => "El filtro especifica cuáles usuarios LDAP deben tener acceso a la instancia %s.", +"users found" => "usuarios encontrados", "Back" => "Volver", +"Continue" => "Continuar", "Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "Advertencia: Las apps user_ldap y user_webdavauth son incompatibles. Puede ser que experimentes comportamientos inesperados. Pedile al administrador que desactive uno de ellos.", "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Atención: El módulo PHP LDAP no está instalado, este elemento no va a funcionar. Por favor, pedile al administrador que lo instale.", "Connection Settings" => "Configuración de Conección", @@ -43,7 +70,7 @@ $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)", +"Case insensitive LDAP server (Windows)" => "Servidor de LDAP insensible 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é", @@ -61,6 +88,9 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Una DN base de grupo por línea", "Group Search Attributes" => "Atributos de búsqueda de grupo", "Group-Member association" => "Asociación Grupo-Miembro", +"Nested Groups" => "Grupos Anidados", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Cuando se activa, grupos que contienen grupos son soportados. (Solo funciona si el atributo de miembro del grupo contiene DNs)", +"Paging chunksize" => "Tamaño del fragmento de paginación", "Special Attributes" => "Atributos Especiales", "Quota Field" => "Campo de cuota", "Quota Default" => "Cuota por defecto", diff --git a/apps/user_ldap/l10n/es_CL.php b/apps/user_ldap/l10n/es_CL.php index b3522617b4..40fa5aad8e 100644 --- a/apps/user_ldap/l10n/es_CL.php +++ b/apps/user_ldap/l10n/es_CL.php @@ -1,5 +1,6 @@ "Error", "_%s group found_::_%s groups found_" => array("",""), "_%s user found_::_%s users found_" => array("",""), "Password" => "Clave" diff --git a/apps/user_ldap/l10n/es_CR.php b/apps/user_ldap/l10n/es_CR.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/es_CR.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/es_MX.php b/apps/user_ldap/l10n/es_MX.php index 16aaa91fd5..bb4c3700ec 100644 --- a/apps/user_ldap/l10n/es_MX.php +++ b/apps/user_ldap/l10n/es_MX.php @@ -33,14 +33,12 @@ $TRANSLATIONS = array( "Save" => "Guardar", "Test Configuration" => "Configuración de prueba", "Help" => "Ayuda", -"Limit the access to %s to groups meeting this criteria:" => "Limitar el acceso a %s a los grupos que cumplan este criterio:", "only those object classes:" => "solamente de estas clases de objeto:", "only from those groups:" => "solamente de estos grupos:", "Edit raw filter instead" => "Editar el filtro en bruto en su lugar", "Raw LDAP filter" => "Filtro LDAP en bruto", "The filter specifies which LDAP groups shall have access to the %s instance." => "El filtro especifica que grupos LDAP tendrán acceso a %s.", "groups found" => "grupos encontrados", -"What attribute shall be used as login name:" => "Que atributo debe ser usado como login:", "LDAP Username:" => "Nombre de usuario LDAP:", "LDAP Email Address:" => "Dirección e-mail LDAP:", "Other Attributes:" => "Otros atributos:", @@ -55,7 +53,6 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Para acceso anónimo, deje DN y contraseña vacíos.", "One Base DN per line" => "Un DN Base por línea", "You can specify Base DN for users and groups in the Advanced tab" => "Puede especificar el DN base para usuarios y grupos en la pestaña Avanzado", -"Limit the access to %s to users meeting this criteria:" => "Limitar el acceso a %s a los usuarios que cumplan el siguiente criterio:", "The filter specifies which LDAP users shall have access to the %s instance." => "El filtro especifica que usuarios LDAP pueden tener acceso a %s.", "users found" => "usuarios encontrados", "Back" => "Atrás", @@ -70,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 10f513c8b8..11941bf4ac 100644 --- a/apps/user_ldap/l10n/et_EE.php +++ b/apps/user_ldap/l10n/et_EE.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Salvesta", "Test Configuration" => "Testi seadistust", "Help" => "Abiinfo", -"Limit the access to %s to groups meeting this criteria:" => "Piira ligipääs %s grupile, mis sobivad kriteeriumiga:", +"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", -"What attribute shall be used as login name:" => "Mis atribuuti kasutada sisselogimise kasutajatunnusena:", +"Users login with this attribute:" => "Logimiseks kasutatkse atribuuti: ", "LDAP Username:" => "LDAP kasutajanimi:", "LDAP Email Address:" => "LDAP e-posti aadress:", "Other Attributes:" => "Muud atribuudid:", @@ -55,7 +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 the access to %s to users meeting this criteria:" => "Piira ligipääs %s kasutajale, kes sobivad kriteeriumiga:", +"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", @@ -70,7 +70,7 @@ $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)", +"Case insensitive LDAP server (Windows)" => "Tõusutundetu 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", @@ -88,6 +88,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 1026e01715..c19cb034ad 100644 --- a/apps/user_ldap/l10n/eu.php +++ b/apps/user_ldap/l10n/eu.php @@ -31,12 +31,10 @@ $TRANSLATIONS = array( "Save" => "Gorde", "Test Configuration" => "Egiaztatu Konfigurazioa", "Help" => "Laguntza", -"Limit the access to %s to groups meeting this criteria:" => "Mugatu sarrera baldintza hauek betetzen dituzten %s taldetara:", "only those object classes:" => "bakarrik objektu klase hauetakoak:", "only from those groups:" => "bakarrik talde hauetakoak:", "The filter specifies which LDAP groups shall have access to the %s instance." => "Iragazkiak zehazten du ze LDAP taldek izango duten sarrera %s instantziara:", "groups found" => "talde aurkituta", -"What attribute shall be used as login name:" => "Sarrera izen gisa erabiliko den atributua:", "LDAP Username:" => "LDAP Erabiltzaile izena:", "LDAP Email Address:" => "LDAP Eposta helbidea:", "Other Attributes:" => "Bestelako atributuak:", @@ -50,7 +48,6 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Sarrera anonimoak gaitzeko utzi DN eta Pasahitza hutsik.", "One Base DN per line" => "DN Oinarri bat lerroko", "You can specify Base DN for users and groups in the Advanced tab" => "Erabiltzaile eta taldeentzako Oinarrizko DN zehaztu dezakezu Aurreratu fitxan", -"Limit the access to %s to users meeting this criteria:" => "Mugatu sarrera hurrengo baldintzak betetzen duten %s erabiltzaileei:", "The filter specifies which LDAP users shall have access to the %s instance." => "Iragazkiak zehazten du ze LDAP erabiltzailek izango duten sarrera %s instantziara:", "users found" => "erabiltzaile aurkituta", "Back" => "Atzera", @@ -64,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/eu_ES.php b/apps/user_ldap/l10n/eu_ES.php new file mode 100644 index 0000000000..6dbfd1955d --- /dev/null +++ b/apps/user_ldap/l10n/eu_ES.php @@ -0,0 +1,7 @@ + array("",""), +"_%s user found_::_%s users found_" => array("",""), +"Save" => "Gorde" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/fa.php b/apps/user_ldap/l10n/fa.php index 688a6ee0d4..62a949f88b 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 ac1dfcc5ab..552fd9f923 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 a5429130d6..44b92077b9 100644 --- a/apps/user_ldap/l10n/fr.php +++ b/apps/user_ldap/l10n/fr.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Sauvegarder", "Test Configuration" => "Tester la configuration", "Help" => "Aide", -"Limit the access to %s to groups meeting this criteria:" => "Limiter l'accès à %s aux groupes respectant ce critère :", +"Groups meeting these criteria are available in %s:" => "Les groupes respectant ces critères sont disponibles dans %s :", "only those object classes:" => "seulement ces classes d'objet :", "only from those groups:" => "seulement de ces groupes :", "Edit raw filter instead" => "Éditer le filtre raw à la place", "Raw LDAP filter" => "Filtre Raw LDAP", "The filter specifies which LDAP groups shall have access to the %s instance." => "Le filtre spécifie quels groupes LDAP doivent avoir accès à l'instance %s.", "groups found" => "groupes trouvés", -"What attribute shall be used as login name:" => "Quel attribut doit être utilisé comme nom de login:", +"Users login with this attribute:" => "Utilisateurs se connectant avec cet attribut :", "LDAP Username:" => "Nom d'utilisateur LDAP :", "LDAP Email Address:" => "Adresse email LDAP :", "Other Attributes:" => "Autres attributs :", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Pour un accès anonyme, laisser le DN utilisateur et le mot de passe vides.", "One Base DN per line" => "Un DN racine par ligne", "You can specify Base DN for users and groups in the Advanced tab" => "Vous pouvez spécifier les DN Racines de vos utilisateurs et groupes via l'onglet Avancé", -"Limit the access to %s to users meeting this criteria:" => "Limiter l'accès à %s aux utilisateurs respectant ce critère :", +"Limit %s access to users meeting these criteria:" => "Limiter l'accès à %s aux utilisateurs respectant ces critères :", "The filter specifies which LDAP users shall have access to the %s instance." => "Le filtre spécifie quels utilisateurs LDAP doivent avoir accès à l'instance %s.", "users found" => "utilisateurs trouvés", "Back" => "Retour", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Un DN racine groupe par ligne", "Group Search Attributes" => "Recherche des attributs du groupe", "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 34e818ef95..82c484bb95 100644 --- a/apps/user_ldap/l10n/gl.php +++ b/apps/user_ldap/l10n/gl.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Gardar", "Test Configuration" => "Probar a configuración", "Help" => "Axuda", -"Limit the access to %s to groups meeting this criteria:" => "Limitar o acceso a %s aos grupos que coincidan con estes criterios:", +"Groups meeting these criteria are available in %s:" => "Os grupos que cumpren estes criterios están dispoñíbeis en %s:", "only those object classes:" => "só as clases de obxecto:", "only from those groups:" => "só dos grupos:", "Edit raw filter instead" => "Editar, no seu canto, o filtro en bruto", "Raw LDAP filter" => "Filtro LDAP en bruto", "The filter specifies which LDAP groups shall have access to the %s instance." => "O filtro especifica que grupos LDAP teñen acceso á instancia %s.", "groups found" => "atopáronse grupos", -"What attribute shall be used as login name:" => "Atributo que utilizar como nome de usuario:", +"Users login with this attribute:" => "Os usuarios inician sesión con este atributo:", "LDAP Username:" => "Nome de usuario LDAP:", "LDAP Email Address:" => "Enderezo de correo LDAP:", "Other Attributes:" => "Outros atributos:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Para o acceso anónimo deixe o DN e o contrasinal baleiros.", "One Base DN per line" => "Un DN base por liña", "You can specify Base DN for users and groups in the Advanced tab" => "Pode especificar a DN base para usuarios e grupos na lapela de «Avanzado»", -"Limit the access to %s to users meeting this criteria:" => "Limitar o acceso a %s aos usuarios que coincidan con estes criterios:", +"Limit %s access to users meeting these criteria:" => "Limitar o acceso a %s para os usuarios que cumpren con estes criterios:", "The filter specifies which LDAP users shall have access to the %s instance." => "O filtro especifica que usuarios LDAP teñen acceso á instancia %s.", "users found" => "atopáronse usuarios", "Back" => "Atrás", @@ -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é", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Un DN base de grupo por liña", "Group Search Attributes" => "Atributos de busca do grupo", "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/hi_IN.php b/apps/user_ldap/l10n/hi_IN.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/hi_IN.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/hu_HU.php b/apps/user_ldap/l10n/hu_HU.php index 2799d0407c..5e05eefd1d 100644 --- a/apps/user_ldap/l10n/hu_HU.php +++ b/apps/user_ldap/l10n/hu_HU.php @@ -33,14 +33,12 @@ $TRANSLATIONS = array( "Save" => "Mentés", "Test Configuration" => "A beállítások tesztelése", "Help" => "Súgó", -"Limit the access to %s to groups meeting this criteria:" => "Korlátozzuk %s elérését a következő feltételeknek megfelelő csoportokra:", "only those object classes:" => "csak ezek az objektumosztályok:", "only from those groups:" => "csak ezek a csoportok:", "Edit raw filter instead" => "Inkább közvetlenül megadom a szűrési kifejezést:", "Raw LDAP filter" => "Az LDAP szűrőkifejezés", "The filter specifies which LDAP groups shall have access to the %s instance." => "A szűrő meghatározza, hogy mely LDAP csoportok lesznek jogosultak %s elérésére.", "groups found" => "csoport van", -"What attribute shall be used as login name:" => "Melyik attribútumot használjuk login névként:", "LDAP Username:" => "LDAP felhasználónév:", "LDAP Email Address:" => "LDAP e-mail cím:", "Other Attributes:" => "Más attribútumok:", @@ -55,7 +53,6 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Bejelentkezés nélküli eléréshez ne töltse ki a DN és Jelszó mezőket!", "One Base DN per line" => "Soronként egy DN-gyökér", "You can specify Base DN for users and groups in the Advanced tab" => "A Haladó fülre kattintva külön DN-gyökér állítható be a felhasználók és a csoportok számára", -"Limit the access to %s to users meeting this criteria:" => "Korlátozzuk %s elérését a következő feltételeknek megfelelő felhasználókra:", "The filter specifies which LDAP users shall have access to the %s instance." => "A szűrő meghatározza, hogy mely LDAP felhasználók lesznek jogosultak %s elérésére.", "users found" => "felhasználó van", "Back" => "Vissza", @@ -70,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", @@ -88,6 +84,7 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Soronként egy csoportfa gyökerét adhatjuk meg", "Group Search Attributes" => "A csoportok lekérdezett attribútumai", "Group-Member association" => "A csoporttagság attribútuma", +"Nested Groups" => "Egymásba ágyazott csoportok", "Special Attributes" => "Különleges attribútumok", "Quota Field" => "Kvóta mező", "Quota Default" => "Alapértelmezett kvóta", diff --git a/apps/user_ldap/l10n/ia.php b/apps/user_ldap/l10n/ia.php index e138fd835f..b29ecbb1d2 100644 --- a/apps/user_ldap/l10n/ia.php +++ b/apps/user_ldap/l10n/ia.php @@ -7,6 +7,7 @@ $TRANSLATIONS = array( "Save" => "Salveguardar", "Help" => "Adjuta", "Password" => "Contrasigno", -"Back" => "Retro" +"Back" => "Retro", +"Continue" => "Continuar" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/id.php b/apps/user_ldap/l10n/id.php index 03071bb1d0..1d42031a49 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 f5e53bdbe9..095a0619ee 100644 --- a/apps/user_ldap/l10n/it.php +++ b/apps/user_ldap/l10n/it.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Salva", "Test Configuration" => "Prova configurazione", "Help" => "Aiuto", -"Limit the access to %s to groups meeting this criteria:" => "Limita l'accesso a %s ai gruppi che verificano questi criteri:", +"Groups meeting these criteria are available in %s:" => "I gruppi che corrispondono a questi criteri sono disponibili in %s:", "only those object classes:" => "solo queste classi di oggetti:", "only from those groups:" => "solo da questi gruppi:", "Edit raw filter instead" => "Modifica invece il filtro grezzo", "Raw LDAP filter" => "Filtro LDAP grezzo", "The filter specifies which LDAP groups shall have access to the %s instance." => "Il filtro specifica quali gruppi LDAP devono avere accesso all'istanza %s.", "groups found" => "gruppi trovati", -"What attribute shall be used as login name:" => "Quale attributo deve essere usato come nome di accesso:", +"Users login with this attribute:" => "Utenti con questo attributo:", "LDAP Username:" => "Nome utente LDAP:", "LDAP Email Address:" => "Indirizzo email LDAP:", "Other Attributes:" => "Altri attributi:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Per l'accesso anonimo, lasciare vuoti i campi DN e Password", "One Base DN per line" => "Un DN base per riga", "You can specify Base DN for users and groups in the Advanced tab" => "Puoi specificare una DN base per gli utenti ed i gruppi nella scheda Avanzate", -"Limit the access to %s to users meeting this criteria:" => "Limita l'accesso a %s ai gruppi che verificano questi criteri:", +"Limit %s access to users meeting these criteria:" => "Limita l'accesso a %s ai gruppi che verificano questi criteri:", "The filter specifies which LDAP users shall have access to the %s instance." => "Il filtro specifica quali utenti LDAP devono avere accesso all'istanza %s.", "users found" => "utenti trovati", "Back" => "Indietro", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Un DN base gruppo per riga", "Group Search Attributes" => "Attributi di ricerca gruppo", "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 new file mode 100644 index 0000000000..1980472164 --- /dev/null +++ b/apps/user_ldap/l10n/ja.php @@ -0,0 +1,112 @@ + "マッピングのクリアに失敗しました。", +"Failed to delete the server configuration" => "サーバー設定の削除に失敗しました", +"The configuration is valid and the connection could be established!" => "設定は有効であり、接続を確立しました!", +"The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "設定は有効ですが、接続に失敗しました。サーバー設定と資格情報を確認してください。", +"The configuration is invalid. Please have a look at the logs for further details." => "設定が無効です。詳細はログを確認してください。", +"No action specified" => "アクションが指定されていません", +"No configuration specified" => "構成が指定されていません", +"No data specified" => "データが指定されていません", +" Could not set configuration %s" => "構成 %s を設定できませんでした", +"Deletion failed" => "削除に失敗しました", +"Take over settings from recent server configuration?" => "最近のサーバー設定から設定を引き継ぎますか?", +"Keep settings?" => "設定を保持しますか?", +"Cannot add server configuration" => "サーバー設定を追加できません", +"mappings cleared" => "マッピングをクリアしました", +"Success" => "成功", +"Error" => "エラー", +"Configuration OK" => "設定OK", +"Configuration incorrect" => "設定に誤りがあります", +"Configuration incomplete" => "設定が不完全です", +"Select groups" => "グループを選択", +"Select object classes" => "オブジェクトクラスを選択", +"Select attributes" => "属性を選択", +"Connection test succeeded" => "接続テストに成功しました", +"Connection test failed" => "接続テストに失敗しました", +"Do you really want to delete the current Server Configuration?" => "現在のサーバー設定を本当に削除してもよろしいですか?", +"Confirm Deletion" => "削除の確認", +"_%s group found_::_%s groups found_" => array("%s グループが見つかりました"), +"_%s user found_::_%s users found_" => array("%s ユーザーが見つかりました"), +"Invalid Host" => "無効なホスト", +"Could not find the desired feature" => "望ましい機能は見つかりませんでした", +"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" => "LDAP フィルタ", +"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:" => "他の属性:", +"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "ログイン実行時に適用するフィルタを定義します。%%uid にはログイン操作におけるユーザー名が入ります。例: \"uid=%%uid\"", +"Add Server Configuration" => "サーバー設定を追加", +"Host" => "ホスト", +"You can omit the protocol, except you require SSL. Then start with ldaps://" => "SSL通信しない場合には、プロトコル名を省略することができます。そうでない場合には、ldaps:// から始めてください。", +"Port" => "ポート", +"User DN" => "ユーザー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は、特定のものに結びつけることはしません。 例えば uid=agent,dc=example,dc=com. だと匿名アクセスの場合、DNとパスワードは空のままです。", +"Password" => "パスワード", +"For anonymous access, leave DN and Password empty." => "匿名アクセスの場合は、DNとパスワードを空にしてください。", +"One Base DN per line" => "1行に1つのベースDN", +"You can specify Base DN for users and groups in the Advanced tab" => "拡張タブでユーザーとグループのベース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" => "戻る", +"Continue" => "続ける", +"Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "警告: user_ldap と user_webdavauth のアプリには互換性がありません。予期せぬ動作をする可能性があります。システム管理者にどちらかを無効にするよう問い合わせてください。", +"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" => "接続設定", +"Configuration Active" => "設定はアクティブです", +"When unchecked, this configuration will be skipped." => "チェックを外すと、この設定はスキップされます。", +"Backup (Replica) Host" => "バックアップ(レプリカ)ホスト", +"Give an optional backup host. It must be a replica of the main LDAP/AD server." => "バックアップホストをオプションで指定することができます。メインのLDAP/ADサーバーのレプリカである必要があります。", +"Backup (Replica) Port" => "バックアップ(レプリカ)ポート", +"Disable Main Server" => "メインサーバーを無効にする", +"Only connect to the replica server." => "レプリカサーバーにのみ接続します。", +"Case insensitive 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", +"in seconds. A change empties the cache." => "秒。変更後にキャッシュがクリアされます。", +"Directory Settings" => "ディレクトリ設定", +"User Display Name Field" => "ユーザー表示名のフィールド", +"The LDAP attribute to use to generate the user's display name." => "ユーザーの表示名の生成に利用するLDAP属性", +"Base User Tree" => "ベースユーザーツリー", +"One User Base DN per line" => "1行に1つのユーザーベースDN", +"User Search Attributes" => "ユーザー検索属性", +"Optional; one attribute per line" => "オプション:1行に1属性", +"Group Display Name Field" => "グループ表示名のフィールド", +"The LDAP attribute to use to generate the groups's display name." => "ユーザのグループ表示名の生成に利用するLDAP属性", +"Base Group Tree" => "ベースグループツリー", +"One Group Base DN per line" => "1行に1つのグループベースDN", +"Group Search Attributes" => "グループ検索属性", +"Group-Member association" => "グループとメンバーの関連付け", +"Nested Groups" => "ネスト化ブロック", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "オンに切り替えたら、グループを含むグループがサポートされます。(グループメンバーの属性がDNを含む場合のみ有効です。)", +"Special Attributes" => "特殊属性", +"Quota Field" => "クォータフィールド", +"Quota Default" => "クォータのデフォルト", +"in bytes" => "バイト", +"Email Field" => "メールフィールド", +"User Home Folder Naming Rule" => "ユーザーのホームフォルダー命名規則", +"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "ユーザー名を空のままにしてください(デフォルト)。もしくは、LDAPもしくはADの属性を指定してください。", +"Internal Username" => "内部ユーザー名", +"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "デフォルトでは、内部ユーザー名はUUID属性から作成されます。これにより、ユーザー名がユニークであり、かつ文字の変換が不要であることを保証します。内部ユーザー名には、[ a-zA-Z0-9_.@- ] の文字のみが有効であるという制限があり、その他の文字は対応する ASCII コードに変換されるか単に無視されます。そのため、他のユーザ名との衝突の回数が増加するでしょう。内部ユーザー名は、内部的にユーザを識別するために用いられ、また、ownCloudにおけるデフォルトのホームフォルダー名としても用いられます。例えば*DAVサービスのように、リモートURLの一部でもあります。この設定により、デフォルトの振る舞いを再定義します。ownCloud 5 以前と同じような振る舞いにするためには、以下のフィールドにユーザー表示名の属性を入力します。空にするとデフォルトの振る舞いとなります。変更は新しくマッピング(追加)されたLDAPユーザーにおいてのみ有効となります。", +"Internal Username Attribute:" => "内部ユーザー名属性:", +"Override UUID detection" => "UUID検出を再定義する", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "デフォルトでは、UUID 属性は自動的に検出されます。UUID属性は、LDAPユーザーとLDAPグループを間違いなく識別するために利用されます。また、もしこれを指定しない場合は、内部ユーザー名はUUIDに基づいて作成されます。この設定は再定義することができ、あなたの選択した属性を用いることができます。選択した属性がユーザーとグループの両方に対して適用でき、かつユニークであることを確認してください。空であればデフォルトの振る舞いとなります。変更は、新しくマッピング(追加)されたLDAPユーザーとLDAPグループに対してのみ有効となります。", +"UUID Attribute for Users:" => "ユーザーの UUID 属性:", +"UUID Attribute for Groups:" => "グループの UUID 属性:", +"Username-LDAP User Mapping" => "ユーザー名とLDAPユーザのマッピング", +"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "ユーザー名は(メタ)データの保存と割り当てに使用されます。ユーザーを正確に識別して認識するために、個々のLDAPユーザは内部ユーザ名を持っています。これは、ユーザー名からLDAPユーザーへのマッピングが必要であることを意味しています。この生成されたユーザ名は、LDAPユーザのUUIDにマッピングされます。加えて、DNがLDAPとのインタラクションを削減するためにキャッシュされますが、識別には利用されません。DNが変わった場合は、変更が検出されます。内部ユーザ名は全体に亘って利用されます。マッピングをクリアすると、いたるところに使われないままの物が残るでしょう。マッピングのクリアは設定に敏感ではありませんが、全てのLDAPの設定に影響を与えます!本番の環境では決してマッピングをクリアしないでください。テストもしくは実験の段階でのみマッピングのクリアを行なってください。", +"Clear Username-LDAP User Mapping" => "ユーザー名とLDAPユーザーのマッピングをクリアする", +"Clear Groupname-LDAP Group Mapping" => "グループ名とLDAPグループのマッピングをクリアする" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_ldap/l10n/ja_JP.php b/apps/user_ldap/l10n/ja_JP.php index 8e98e80370..d13deafe6c 100644 --- a/apps/user_ldap/l10n/ja_JP.php +++ b/apps/user_ldap/l10n/ja_JP.php @@ -1,18 +1,18 @@ "マッピングのクリアに失敗しました。", -"Failed to delete the server configuration" => "サーバ設定の削除に失敗しました", +"Failed to delete the server configuration" => "サーバー設定の削除に失敗しました", "The configuration is valid and the connection could be established!" => "設定は有効であり、接続を確立しました!", -"The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "設定は有効ですが、接続に失敗しました。サーバ設定と資格情報を確認して下さい。", +"The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "設定は有効ですが、接続に失敗しました。サーバー設定と資格情報を確認してください。", "The configuration is invalid. Please have a look at the logs for further details." => "設定が無効です。詳細はログを確認してください。", "No action specified" => "アクションが指定されていません", "No configuration specified" => "構成が指定されていません", "No data specified" => "データが指定されていません", " Could not set configuration %s" => "構成 %s を設定できませんでした", "Deletion failed" => "削除に失敗しました", -"Take over settings from recent server configuration?" => "最近のサーバ設定から設定を引き継ぎますか?", +"Take over settings from recent server configuration?" => "最近のサーバー設定から設定を引き継ぎますか?", "Keep settings?" => "設定を保持しますか?", -"Cannot add server configuration" => "サーバ設定を追加できません", +"Cannot add server configuration" => "サーバー設定を追加できません", "mappings cleared" => "マッピングをクリアしました", "Success" => "成功", "Error" => "エラー", @@ -24,40 +24,40 @@ $TRANSLATIONS = array( "Select attributes" => "属性を選択", "Connection test succeeded" => "接続テストに成功しました", "Connection test failed" => "接続テストに失敗しました", -"Do you really want to delete the current Server Configuration?" => "現在のサーバ設定を本当に削除してもよろしいですか?", +"Do you really want to delete the current Server Configuration?" => "現在のサーバー設定を本当に削除してもよろしいですか?", "Confirm Deletion" => "削除の確認", "_%s group found_::_%s groups found_" => array("%s グループが見つかりました"), -"_%s user found_::_%s users found_" => array("%s ユーザが見つかりました"), +"_%s user found_::_%s users found_" => array("%s ユーザーが見つかりました"), "Invalid Host" => "無効なホスト", "Could not find the desired feature" => "望ましい機能は見つかりませんでした", "Save" => "保存", "Test Configuration" => "設定をテスト", "Help" => "ヘルプ", -"Limit the access to %s to groups meeting this criteria:" => "この基準に合致するグループに %s へのアクセスを制限:", +"Groups meeting these criteria are available in %s:" => "これらの基準を満たすグループが %s で利用可能:", "only those object classes:" => "それらのオブジェクトクラスのみ:", "only from those groups:" => "それらのグループからのみ:", "Edit raw filter instead" => "フィルタを編集", "Raw LDAP filter" => "LDAP フィルタ", "The filter specifies which LDAP groups shall have access to the %s instance." => "フィルタは、どの LDAP グループが %s にアクセスするかを指定します。", "groups found" => "グループが見つかりました", -"What attribute shall be used as login name:" => "ログイン名として利用する属性:", -"LDAP Username:" => "LDAP ユーザ名:", +"Users login with this attribute:" => "この属性でユーザーログイン:", +"LDAP Username:" => "LDAP ユーザー名:", "LDAP Email Address:" => "LDAP メールアドレス:", "Other Attributes:" => "他の属性:", -"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "ログイン実行時に適用するフィルタを定義します。%%uid にはログイン操作におけるユーザ名が入ります。例: \"uid=%%uid\"", -"Add Server Configuration" => "サーバ設定を追加", +"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "ログイン実行時に適用するフィルタを定義します。%%uid にはログイン操作におけるユーザー名が入ります。例: \"uid=%%uid\"", +"Add Server Configuration" => "サーバー設定を追加", "Host" => "ホスト", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "SSL通信しない場合には、プロトコル名を省略することができます。そうでない場合には、ldaps:// から始めてください。", "Port" => "ポート", -"User DN" => "ユーザDN", +"User DN" => "ユーザー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は、特定のものに結びつけることはしません。 例えば uid=agent,dc=example,dc=com. だと匿名アクセスの場合、DNとパスワードは空のままです。", "Password" => "パスワード", "For anonymous access, leave DN and Password empty." => "匿名アクセスの場合は、DNとパスワードを空にしてください。", "One Base DN per line" => "1行に1つのベースDN", -"You can specify Base DN for users and groups in the Advanced tab" => "拡張タブでユーザとグループのベースDNを指定することができます。", -"Limit the access to %s to users meeting this criteria:" => "この基準に合致するユーザに %s へのアクセスを制限:", -"The filter specifies which LDAP users shall have access to the %s instance." => "フィルタは、どの LDAP ユーザが %s にアクセスするかを指定します。", -"users found" => "ユーザが見つかりました", +"You can specify Base DN for users and groups in the Advanced tab" => "拡張タブでユーザーとグループのベース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" => "戻る", "Continue" => "続ける", "Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "警告: user_ldap と user_webdavauth のアプリには互換性がありません。予期せぬ動作をする可能性があります。システム管理者にどちらかを無効にするよう問い合わせてください。", @@ -66,21 +66,21 @@ $TRANSLATIONS = array( "Configuration Active" => "設定はアクティブです", "When unchecked, this configuration will be skipped." => "チェックを外すと、この設定はスキップされます。", "Backup (Replica) Host" => "バックアップ(レプリカ)ホスト", -"Give an optional backup host. It must be a replica of the main LDAP/AD server." => "バックアップホストをオプションで指定することができます。メインのLDAP/ADサーバのレプリカである必要があります。", +"Give an optional backup host. It must be a replica of the main LDAP/AD server." => "バックアップホストをオプションで指定することができます。メインのLDAP/ADサーバーのレプリカである必要があります。", "Backup (Replica) Port" => "バックアップ(レプリカ)ポート", -"Disable Main Server" => "メインサーバを無効にする", +"Disable Main Server" => "メインサーバーを無効にする", "Only connect to the replica server." => "レプリカサーバーにのみ接続します。", -"Case insensitve LDAP server (Windows)" => "大文字/小文字を区別しないLDAPサーバ(Windows)", +"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 サーバにインポートしてください。", +"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", "in seconds. A change empties the cache." => "秒。変更後にキャッシュがクリアされます。", "Directory Settings" => "ディレクトリ設定", -"User Display Name Field" => "ユーザ表示名のフィールド", -"The LDAP attribute to use to generate the user's display name." => "ユーザの表示名の生成に利用するLDAP属性", -"Base User Tree" => "ベースユーザツリー", -"One User Base DN per line" => "1行に1つのユーザベースDN", -"User Search Attributes" => "ユーザ検索属性", +"User Display Name Field" => "ユーザー表示名のフィールド", +"The LDAP attribute to use to generate the user's display name." => "ユーザーの表示名の生成に利用するLDAP属性", +"Base User Tree" => "ベースユーザーツリー", +"One User Base DN per line" => "1行に1つのユーザーベースDN", +"User Search Attributes" => "ユーザー検索属性", "Optional; one attribute per line" => "オプション:1行に1属性", "Group Display Name Field" => "グループ表示名のフィールド", "The LDAP attribute to use to generate the groups's display name." => "ユーザのグループ表示名の生成に利用するLDAP属性", @@ -88,23 +88,25 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "1行に1つのグループベースDN", "Group Search Attributes" => "グループ検索属性", "Group-Member association" => "グループとメンバーの関連付け", +"Nested Groups" => "ネスト化ブロック", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "オンに切り替えたら、グループを含むグループがサポートされます。(グループメンバーの属性がDNを含む場合のみ有効です。)", "Special Attributes" => "特殊属性", "Quota Field" => "クォータフィールド", "Quota Default" => "クォータのデフォルト", "in bytes" => "バイト", "Email Field" => "メールフィールド", -"User Home Folder Naming Rule" => "ユーザのホームフォルダ命名規則", -"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "ユーザ名を空のままにしてください(デフォルト)。そうでない場合は、LDAPもしくはADの属性を指定してください。", -"Internal Username" => "内部ユーザ名", -"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "デフォルトでは、内部ユーザ名はUUID属性から作成されます。これにより、ユーザ名がユニークであり、かつ文字の変換が不要であることを保証します。内部ユーザ名には、[ a-zA-Z0-9_.@- ] の文字のみが有効であるという制限があり、その他の文字は対応する ASCII コードに変換されるか単に無視されます。そのため、他のユーザ名との衝突の回数が増加するでしょう。内部ユーザ名は、内部的にユーザを識別するために用いられ、また、ownCloudにおけるデフォルトのホームフォルダ名としても用いられます。例えば*DAVサービスのように、リモートURLの一部でもあります。この設定により、デフォルトの振る舞いを再定義します。ownCloud 5 以前と同じような振る舞いにするためには、以下のフィールドにユーザ表示名の属性を入力します。空にするとデフォルトの振る舞いとなります。変更は新しくマッピング(追加)されたLDAPユーザにおいてのみ有効となります。", -"Internal Username Attribute:" => "内部ユーザ名属性:", +"User Home Folder Naming Rule" => "ユーザーのホームフォルダー命名規則", +"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "ユーザー名を空のままにしてください(デフォルト)。もしくは、LDAPもしくはADの属性を指定してください。", +"Internal Username" => "内部ユーザー名", +"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "デフォルトでは、内部ユーザー名はUUID属性から作成されます。これにより、ユーザー名がユニークであり、かつ文字の変換が不要であることを保証します。内部ユーザー名には、[ a-zA-Z0-9_.@- ] の文字のみが有効であるという制限があり、その他の文字は対応する ASCII コードに変換されるか単に無視されます。そのため、他のユーザ名との衝突の回数が増加するでしょう。内部ユーザー名は、内部的にユーザを識別するために用いられ、また、ownCloudにおけるデフォルトのホームフォルダー名としても用いられます。例えば*DAVサービスのように、リモートURLの一部でもあります。この設定により、デフォルトの振る舞いを再定義します。ownCloud 5 以前と同じような振る舞いにするためには、以下のフィールドにユーザー表示名の属性を入力します。空にするとデフォルトの振る舞いとなります。変更は新しくマッピング(追加)されたLDAPユーザーにおいてのみ有効となります。", +"Internal Username Attribute:" => "内部ユーザー名属性:", "Override UUID detection" => "UUID検出を再定義する", -"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "デフォルトでは、UUID 属性は自動的に検出されます。UUID属性は、LDAPユーザとLDAPグループを間違いなく識別するために利用されます。また、もしこれを指定しない場合は、内部ユーザ名はUUIDに基づいて作成されます。この設定は再定義することができ、あなたの選択した属性を用いることができます。選択した属性がユーザとグループの両方に対して適用でき、かつユニークであることを確認してください。空であればデフォルトの振る舞いとなります。変更は、新しくマッピング(追加)されたLDAPユーザとLDAPグループに対してのみ有効となります。", -"UUID Attribute for Users:" => "ユーザの UUID 属性:", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "デフォルトでは、UUID 属性は自動的に検出されます。UUID属性は、LDAPユーザーとLDAPグループを間違いなく識別するために利用されます。また、もしこれを指定しない場合は、内部ユーザー名はUUIDに基づいて作成されます。この設定は再定義することができ、あなたの選択した属性を用いることができます。選択した属性がユーザーとグループの両方に対して適用でき、かつユニークであることを確認してください。空であればデフォルトの振る舞いとなります。変更は、新しくマッピング(追加)されたLDAPユーザーとLDAPグループに対してのみ有効となります。", +"UUID Attribute for Users:" => "ユーザーの UUID 属性:", "UUID Attribute for Groups:" => "グループの UUID 属性:", -"Username-LDAP User Mapping" => "ユーザ名とLDAPユーザのマッピング", -"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "ユーザ名は(メタ)データの保存と割り当てに使用されます。ユーザを正確に識別して認識するために、個々のLDAPユーザは内部ユーザ名を持っています。これは、ユーザ名からLDAPユーザへのマッピングが必要であることを意味しています。この生成されたユーザ名は、LDAPユーザのUUIDにマッピングされます。加えて、DNがLDAPとのインタラクションを削減するためにキャッシュされますが、識別には利用されません。DNが変わった場合は、変更が検出されます。内部ユーザ名は全体に亘って利用されます。マッピングをクリアすると、いたるところに使われないままの物が残るでしょう。マッピングのクリアは設定に敏感ではありませんが、全てのLDAPの設定に影響を与えます!本番の環境では決してマッピングをクリアしないでください。テストもしくは実験の段階でのみマッピングのクリアを行なってください。", -"Clear Username-LDAP User Mapping" => "ユーザ名とLDAPユーザのマッピングをクリアする", +"Username-LDAP User Mapping" => "ユーザー名とLDAPユーザのマッピング", +"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "ユーザー名は(メタ)データの保存と割り当てに使用されます。ユーザーを正確に識別して認識するために、個々のLDAPユーザは内部ユーザ名を持っています。これは、ユーザー名からLDAPユーザーへのマッピングが必要であることを意味しています。この生成されたユーザ名は、LDAPユーザのUUIDにマッピングされます。加えて、DNがLDAPとのインタラクションを削減するためにキャッシュされますが、識別には利用されません。DNが変わった場合は、変更が検出されます。内部ユーザ名は全体に亘って利用されます。マッピングをクリアすると、いたるところに使われないままの物が残るでしょう。マッピングのクリアは設定に敏感ではありませんが、全てのLDAPの設定に影響を与えます!本番の環境では決してマッピングをクリアしないでください。テストもしくは実験の段階でのみマッピングのクリアを行なってください。", +"Clear Username-LDAP User Mapping" => "ユーザー名とLDAPユーザーのマッピングをクリアする", "Clear Groupname-LDAP Group Mapping" => "グループ名とLDAPグループのマッピングをクリアする" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_ldap/l10n/jv.php b/apps/user_ldap/l10n/jv.php new file mode 100644 index 0000000000..3a1e002311 --- /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 ffdf765551..3ee307b55c 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/km.php b/apps/user_ldap/l10n/km.php index bba52d53a1..ad3cc4882c 100644 --- a/apps/user_ldap/l10n/km.php +++ b/apps/user_ldap/l10n/km.php @@ -1,6 +1,20 @@ "លុប​ការ​កំណត់​រចនា​សម្ព័ន្ធ​ម៉ាស៊ីន​បម្រើ មិន​បាន​សម្រេច", +"Deletion failed" => "លុប​មិន​បាន​សម្រេច", +"Keep settings?" => "រក្សា​ទុក​ការ​កំណត់?", +"Cannot add server configuration" => "មិន​អាច​បន្ថែម​ការ​កំណត់​រចនាសម្ព័ន្ធ​ម៉ាស៊ីន​បម្រើ", +"Error" => "កំហុស", +"Connection test succeeded" => "សាក​ល្បង​ការ​ត​ភ្ជាប់ បាន​ជោគជ័យ", +"Connection test failed" => "សាកល្បង​ការ​តភ្ជាប់ មិន​បាន​សម្រេច", +"Do you really want to delete the current Server Configuration?" => "តើ​អ្នក​ពិត​ជា​ចង់​លុប​ការ​កំណត់​រចនាសម្ព័ន្ធ​ម៉ាស៊ីន​បម្រើ​បច្ចុប្បន្ន​មែន​ទេ?", +"Confirm Deletion" => "បញ្ជាក់​ការ​លុប", "_%s group found_::_%s groups found_" => array(""), -"_%s user found_::_%s users found_" => array("") +"_%s user found_::_%s users found_" => array(""), +"Save" => "រក្សាទុក", +"Help" => "ជំនួយ", +"Add Server Configuration" => "បន្ថែម​ការ​កំណត់​រចនាសម្ព័ន្ធ​ម៉ាស៊ីន​បម្រើ", +"Host" => "ម៉ាស៊ីន​ផ្ទុក", +"Password" => "ពាក្យសម្ងាត់" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_ldap/l10n/ko.php b/apps/user_ldap/l10n/ko.php index 2d861f27ba..1ae63bd4d2 100644 --- a/apps/user_ldap/l10n/ko.php +++ b/apps/user_ldap/l10n/ko.php @@ -33,14 +33,12 @@ $TRANSLATIONS = array( "Save" => "저장", "Test Configuration" => "설정 시험", "Help" => "도움말", -"Limit the access to %s to groups meeting this criteria:" => "다음 조건을 만족하는 그룹만 %s 접근 허용:", "only those object classes:" => "다음 객체 클래스만:", "only from those groups:" => "다음 그룹에서만:", "Edit raw filter instead" => "필터 직접 편집", "Raw LDAP filter" => "LDAP 필터", "The filter specifies which LDAP groups shall have access to the %s instance." => "이 필터는 %s에 접근할 수 있는 LDAP 그룹을 설정합니다.", "groups found" => "그룹 찾음", -"What attribute shall be used as login name:" => "로그인 이름으로 사용할 속성:", "LDAP Username:" => "LDAP 사용자 이름:", "LDAP Email Address:" => "LDAP 이메일 주소:", "Other Attributes:" => "기타 속성:", @@ -55,7 +53,6 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "익명 접근을 허용하려면 DN과 암호를 비워 두십시오.", "One Base DN per line" => "기본 DN을 한 줄에 하나씩 입력하십시오", "You can specify Base DN for users and groups in the Advanced tab" => "고급 탭에서 사용자 및 그룹에 대한 기본 DN을 지정할 수 있습니다.", -"Limit the access to %s to users meeting this criteria:" => "다음 조건을 만족하는 사용자만 %s 접근 허용:", "The filter specifies which LDAP users shall have access to the %s instance." => "이 필터는 %s에 접근할 수 있는 LDAP 사용자를 설정합니다.", "users found" => "사용자 찾음", "Back" => "뒤로", @@ -70,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 769f17e633..e3cb206e2d 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/ml.php b/apps/user_ldap/l10n/ml.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/ml.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/mn.php b/apps/user_ldap/l10n/mn.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/mn.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/nb_NO.php b/apps/user_ldap/l10n/nb_NO.php index 625ec79d76..dd4af3e759 100644 --- a/apps/user_ldap/l10n/nb_NO.php +++ b/apps/user_ldap/l10n/nb_NO.php @@ -1,23 +1,48 @@ "Klarte ikke å nullstille tilknytningene.", "Failed to delete the server configuration" => "Klarte ikke å slette tjener-konfigurasjonen.", "The configuration is valid and the connection could be established!" => "Konfigurasjonen er i orden og tilkoblingen skal være etablert!", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "Konfigurasjonen er i orden, men Bind mislyktes. Vennligst sjekk tjener-konfigurasjonen og påloggingsinformasjonen.", +"The configuration is invalid. Please have a look at the logs for further details." => "Konfigurasjonen er ikke gyldig. Sjekk loggene for flere detaljer.", +"No action specified" => "Ingen handling spesifisert", +"No configuration specified" => "Ingen konfigurasjon spesifisert", +"No data specified" => "Ingen data spesifisert", +" Could not set configuration %s" => "Klarte ikke å sette konfigurasjon %s", "Deletion failed" => "Sletting mislyktes", "Take over settings from recent server configuration?" => "Hent innstillinger fra tidligere tjener-konfigurasjon?", "Keep settings?" => "Behold innstillinger?", "Cannot add server configuration" => "Kan ikke legge til tjener-konfigurasjon", +"mappings cleared" => "tilknytninger nullstilt", "Success" => "Suksess", "Error" => "Feil", +"Configuration OK" => "Konfigurasjon OK", +"Configuration incorrect" => "Konfigurasjon feil", +"Configuration incomplete" => "Konfigurasjon ufullstendig", "Select groups" => "Velg grupper", +"Select object classes" => "Velg objektklasser", +"Select attributes" => "Velg attributter", "Connection test succeeded" => "Tilkoblingstest lyktes", "Connection test failed" => "Tilkoblingstest mislyktes", "Do you really want to delete the current Server Configuration?" => "Er du sikker på at du vil slette aktiv tjener-konfigurasjon?", "Confirm Deletion" => "Bekreft sletting", -"_%s group found_::_%s groups found_" => array("",""), -"_%s user found_::_%s users found_" => array("",""), +"_%s group found_::_%s groups found_" => array("%s gruppe funnet","%s grupper funnet"), +"_%s user found_::_%s users found_" => array("%s bruker funnet","%s brukere funnet"), +"Invalid Host" => "Ugyldig tjener", +"Could not find the desired feature" => "Fant ikke den ønskede funksjonaliteten", "Save" => "Lagre", +"Test Configuration" => "Test konfigurasjonen", "Help" => "Hjelp", +"only those object classes:" => "kun de objektklassene:", +"only from those groups:" => "kun fra de gruppene:", +"Edit raw filter instead" => "Rediger ubearbeidet filter i stedet", +"Raw LDAP filter" => "Ubearbeidet LDAP-filter", +"The filter specifies which LDAP groups shall have access to the %s instance." => "Filteret spesifiserer hvilke LDAP-grupper som skal ha tilgang til %s-instansen.", +"groups found" => "grupper funnet", +"LDAP Username:" => "LDAP-brukernavn:", +"LDAP Email Address:" => "LDAP-epostadresse:", +"Other Attributes:" => "Andre attributter:", +"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "Definerer filteret som skal brukes når innlogging forsøkes. %%uid erstatter brukernavnet i innloggingshandlingen. Eksempel: \"uid=%%uid\"", "Add Server Configuration" => "Legg til tjener-konfigurasjon", "Host" => "Tjener", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "Du kan utelate protokollen, men du er påkrevd å bruke SSL. Deretter starte med ldaps://", @@ -28,23 +53,54 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "For anonym tilgang, la DN- og passord-feltet stå tomt.", "One Base DN per line" => "En hoved DN pr. linje", "You can specify Base DN for users and groups in the Advanced tab" => "Du kan spesifisere Base DN for brukere og grupper under Avansert fanen", +"The filter specifies which LDAP users shall have access to the %s instance." => "Filteret spesifiserer hvilke LDAP-brukere som skal ha tilgang til %s-instansen.", +"users found" => "brukere funnet", "Back" => "Tilbake", "Continue" => "Fortsett", +"Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "Advarsel: Appene user_ldap og user_webdavauth er ikke kompatible med hverandre. Uventet oppførsel kan forekomme. Be systemadministratoren om å deaktivere en av dem.", "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Warning: PHP LDAP modulen er ikke installert, hjelperen vil ikke virke. Vennligst be din system-administrator om å installere den.", +"Connection Settings" => "Innstillinger for tilkobling", "Configuration Active" => "Konfigurasjon aktiv", "When unchecked, this configuration will be skipped." => "Når ikke huket av så vil denne konfigurasjonen bli hoppet over.", "Backup (Replica) Host" => "Sikkerhetskopierings (Replica) vert", -"Case insensitve LDAP server (Windows)" => "Case-insensitiv LDAP tjener (Windows)", +"Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Oppgi en valgfri reservetjener. Den må være en replika av hovedtjeneren for LDAP/AD.", +"Backup (Replica) Port" => "Reserve (Replika) Port", +"Disable Main Server" => "Deaktiver hovedtjeneren", +"Only connect to the replica server." => "Koble til bare replika-tjeneren.", "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", "in seconds. A change empties the cache." => "i sekunder. En endring tømmer bufferen.", +"Directory Settings" => "Innstillinger for Katalog", "User Display Name Field" => "Vis brukerens navnfelt", +"The LDAP attribute to use to generate the user's display name." => "LDAP-attributten som skal brukes til å generere brukerens visningsnavn.", "Base User Tree" => "Hovedbruker tre", "One User Base DN per line" => "En Bruker Base DN pr. linje", +"User Search Attributes" => "Attributter for brukersøk", +"Optional; one attribute per line" => "Valgfritt, en attributt pr. linje", "Group Display Name Field" => "Vis gruppens navnfelt", +"The LDAP attribute to use to generate the groups's display name." => "LDAP-attributten som skal brukes til å generere gruppens visningsnavn.", "Base Group Tree" => "Hovedgruppe tre", "One Group Base DN per line" => "En gruppe hoved-DN pr. linje", +"Group Search Attributes" => "Attributter for gruppesøk", "Group-Member association" => "gruppe-medlem assosiasjon", +"Special Attributes" => "Spesielle attributter", +"Quota Field" => "Felt med lagringskvote", +"Quota Default" => "Standard lagringskvote", "in bytes" => "i bytes", -"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "La stå tom for brukernavn (standard). Ellers, spesifiser en LDAP/AD attributt." +"Email Field" => "Felt med e-postadresse", +"User Home Folder Naming Rule" => "Navneregel for brukers hjemmemappe", +"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "La stå tom for brukernavn (standard). Ellers, spesifiser en LDAP/AD attributt.", +"Internal Username" => "Internt brukernavn", +"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "Som standard vil det interne brukernavnet bli laget utifra UUID-attributten. Dette sikrer at brukernavnet er unikt og at det ikke er nødvendig å konvertere tegn. Det interne brukernavnet har den begrensningen at bare disse tegnene er tillatt: [ a-zA-Z0-9_.@- ]. Andre tegn erstattes av tilsvarende ASCII-tegn eller blir ganske enkelt utelatt. Ved kollisjon blir et nummer lagt til / øket. Det interne brukernavnet brukes til å identifisere en bruker internt. Det er også standardnavnet på brukerens hjemmemappe. Det er også med i fjern-URL-er, for eksempel for alle *DAV-tjenester. Med denne innstillingen kan standard oppførsel overstyres. For å få en oppførsel som likner oppførselen før ownCloud 5, legg inn attributten for brukerens visningsnavn i dette feltet. La feltet stå tomt for standard oppførsel. Endringer vil kun påvirke nylig tilknyttede (opprettede) LDAP-brukere.", +"Internal Username Attribute:" => "Attributt for internt brukernavn:", +"Override UUID detection" => "Overstyr UUID-oppdaging", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "Som standard blir UUID-attributten oppdaget automatisk. UUID-attributten brukes til å identifisere LDAP-brukere og -grupper uten tvil. Det interne brukernavnet vil også bli laget basert på UUID, hvis ikke annet er spesifisert ovenfor. Du kan overstyre innstillingen og oppgi den attributten du ønsker. Du må forsikre det om at din valgte attributt kan hentes ut både for brukere og for grupper og at den er unik. La stå tomt for standard oppførsel. Endringer vil kun påvirke nylig tilknyttede (opprettede) LDAP-brukere og -grupper.", +"UUID Attribute for Users:" => "UUID-attributt for brukere:", +"UUID Attribute for Groups:" => "UUID-attributt for grupper:", +"Username-LDAP User Mapping" => "Tilknytning av brukernavn til LDAP-bruker", +"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "Brukernavn brukes til å lagre og tilordne (meta)data. For at brukere skal identifiseres og gjenkjennes presist, vil hver LDAP-bruker ha et internt brukernavn. Dette krever en tilknytning fra brukernavn til LDAP-bruker. Brukernavn som opprettes blir knyttet til LDAP-brukerens UUID. I tillegg mellomlagres DN for å redusere LDAP-kommunikasjon, men det brukes ikke til identifisering. Hvis DN endres vil endringene bli oppdaget. Det interne brukernavnet brukes alle steder. Nullstilling av tilknytningene vil etterlate seg rester overalt. Nullstilling av tilknytningene skjer ikke pr. konfigurasjon, det påvirker alle LDAP-konfigurasjoner! Nullstill aldri tilknytningene i et produksjonsmiljø, kun ved testing eller eksperimentering.", +"Clear Username-LDAP User Mapping" => "Nullstill tilknytning av brukernavn til LDAP-bruker", +"Clear Groupname-LDAP Group Mapping" => "Nullstill tilknytning av gruppenavn til LDAP-gruppe" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/nl.php b/apps/user_ldap/l10n/nl.php index bfe96f4268..196e5a52d1 100644 --- a/apps/user_ldap/l10n/nl.php +++ b/apps/user_ldap/l10n/nl.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Bewaren", "Test Configuration" => "Test configuratie", "Help" => "Help", -"Limit the access to %s to groups meeting this criteria:" => "Beperk toegang tot %s tot groepen die voldoen aan deze criteria:", +"Groups meeting these criteria are available in %s:" => "Groepsafspraken die voldoen aan deze criteria zijn beschikbaar in %s:", "only those object classes:" => "alleen deze objectklassen", "only from those groups:" => "alleen van deze groepen:", "Edit raw filter instead" => "Bewerk raw filter", "Raw LDAP filter" => "Raw LDAP filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "Dit filter geeft aan welke LDAP groepen toegang hebben tot %s.", "groups found" => "groepen gevonden", -"What attribute shall be used as login name:" => "Welk attribuut moet worden gebruikt als inlognaam:", +"Users login with this attribute:" => "Gebruikers loggen in met dit attribuut:", "LDAP Username:" => "LDAP Username:", "LDAP Email Address:" => "LDAP e-mailadres:", "Other Attributes:" => "Overige attributen:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Voor anonieme toegang, laat de DN en het wachtwoord leeg.", "One Base DN per line" => "Een Base DN per regel", "You can specify Base DN for users and groups in the Advanced tab" => "Je kunt het Base DN voor gebruikers en groepen specificeren in het tab Geavanceerd.", -"Limit the access to %s to users meeting this criteria:" => "Beperk toegang tot %s tot gebruikers die voldoen aan deze criteria:", +"Limit %s access to users meeting these criteria:" => "Beperk %s toegang tot gebruikers die voldoen aan deze criteria:", "The filter specifies which LDAP users shall have access to the %s instance." => "Dit filter geeft aan welke LDAP gebruikers toegang hebben tot %s.", "users found" => "gebruikers gevonden", "Back" => "Terug", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Een Group Base DN per regel", "Group Search Attributes" => "Attributen voor groepszoekopdrachten", "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/or_IN.php b/apps/user_ldap/l10n/or_IN.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/or_IN.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/pl.php b/apps/user_ldap/l10n/pl.php index 056718a027..988e44dbe3 100644 --- a/apps/user_ldap/l10n/pl.php +++ b/apps/user_ldap/l10n/pl.php @@ -4,6 +4,11 @@ $TRANSLATIONS = array( "Failed to delete the server configuration" => "Nie można usunąć konfiguracji serwera", "The configuration is valid and the connection could be established!" => "Konfiguracja jest prawidłowa i można ustanowić połączenie!", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "Konfiguracja jest prawidłowa, ale Bind nie. Sprawdź ustawienia serwera i poświadczenia.", +"The configuration is invalid. Please have a look at the logs for further details." => "Konfiguracja jest nieprawidłowa. Proszę rzucić okiem na dzienniki dalszych szczegółów.", +"No action specified" => "Nie określono akcji", +"No configuration specified" => "Nie określono konfiguracji", +"No data specified" => "Nie określono danych", +" Could not set configuration %s" => "Nie można ustawić konfiguracji %s", "Deletion failed" => "Usunięcie nie powiodło się", "Take over settings from recent server configuration?" => "Przejmij ustawienia z ostatnich konfiguracji serwera?", "Keep settings?" => "Zachować ustawienia?", @@ -11,16 +16,35 @@ $TRANSLATIONS = array( "mappings cleared" => "Mapoanie wyczyszczone", "Success" => "Sukces", "Error" => "Błąd", +"Configuration OK" => "Konfiguracja poprawna", +"Configuration incorrect" => "Konfiguracja niepoprawna", +"Configuration incomplete" => "Konfiguracja niekompletna", "Select groups" => "Wybierz grupy", +"Select object classes" => "Wybierz obiekty klas", +"Select attributes" => "Wybierz atrybuty", "Connection test succeeded" => "Test połączenia udany", "Connection test failed" => "Test połączenia nie udany", "Do you really want to delete the current Server Configuration?" => "Czy chcesz usunąć bieżącą konfigurację serwera?", "Confirm Deletion" => "Potwierdź usunięcie", -"_%s group found_::_%s groups found_" => array("","",""), -"_%s user found_::_%s users found_" => array("","",""), +"_%s group found_::_%s groups found_" => array("%s znaleziona grupa","%s znalezionych grup","%s znalezionych grup"), +"_%s user found_::_%s users found_" => array("%s znaleziony użytkownik","%s znalezionych użytkowników","%s znalezionych użytkowników"), +"Invalid Host" => "Niepoprawny Host", +"Could not find the desired feature" => "Nie można znaleźć żądanej funkcji", "Save" => "Zapisz", "Test Configuration" => "Konfiguracja testowa", "Help" => "Pomoc", +"Groups meeting these criteria are available in %s:" => "Przyłączenie do grupy z tymi ustawieniami dostępne jest w %s:", +"only those object classes:" => "tylko te klasy obiektów:", +"only from those groups:" => "tylko z tych grup:", +"Edit raw filter instead" => "Edytuj zamiast tego czysty filtr", +"Raw LDAP filter" => "Czysty filtr LDAP", +"The filter specifies which LDAP groups shall have access to the %s instance." => "Filtr określa, które grupy LDAP powinny mieć dostęp do instancji %s.", +"groups found" => "grup znaleziono", +"Users login with this attribute:" => "Użytkownicy zalogowani z tymi ustawieniami:", +"LDAP Username:" => "Nazwa użytkownika LDAP:", +"LDAP Email Address:" => "LDAP Adres Email:", +"Other Attributes:" => "Inne atrybuty:", +"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "Określa jakiego filtru użyć podczas próby zalogowania. %%uid zastępuje nazwę użytkownika w procesie logowania. Przykład: \"uid=%%uid\"", "Add Server Configuration" => "Dodaj konfigurację servera", "Host" => "Host", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "Można pominąć protokół, z wyjątkiem wymaganego protokołu SSL. Następnie uruchom z ldaps://", @@ -31,8 +55,12 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Dla dostępu anonimowego pozostawić DN i hasło puste.", "One Base DN per line" => "Jedna baza DN na linię", "You can specify Base DN for users and groups in the Advanced tab" => "Bazę DN można określić dla użytkowników i grup w karcie Zaawansowane", +"Limit %s access to users meeting these criteria:" => "Limit %s dostępu do podłączania użytkowników z tymi ustawieniami:", +"The filter specifies which LDAP users shall have access to the %s instance." => "Filtr określa, którzy użytkownicy LDAP powinni mieć dostęp do instancji %s.", +"users found" => "użytkownicy znalezieni", "Back" => "Wróć", "Continue" => "Kontynuuj ", +"Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "Ostrzeżenie: Aplikacje user_ldap i user_webdavauth nie są kompatybilne. Mogą powodować nieoczekiwane zachowanie. Poproś administratora o wyłączenie jednej z nich.", "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Ostrzeżenie: Moduł PHP LDAP nie jest zainstalowany i nie będzie działał. Poproś administratora o włączenie go.", "Connection Settings" => "Konfiguracja połączeń", "Configuration Active" => "Konfiguracja archiwum", @@ -42,21 +70,28 @@ $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", "in seconds. A change empties the cache." => "w sekundach. Zmiana opróżnia pamięć podręczną.", "Directory Settings" => "Ustawienia katalogów", "User Display Name Field" => "Pole wyświetlanej nazwy użytkownika", +"The LDAP attribute to use to generate the user's display name." => "Atrybut LDAP służący do generowania wyświetlanej nazwy użytkownika ownCloud.", "Base User Tree" => "Drzewo bazy użytkowników", "One User Base DN per line" => "Jeden użytkownik Bazy DN na linię", "User Search Attributes" => "Szukaj atrybutów", "Optional; one attribute per line" => "Opcjonalnie; jeden atrybut w wierszu", "Group Display Name Field" => "Pole wyświetlanej nazwy grupy", +"The LDAP attribute to use to generate the groups's display name." => "Atrybut LDAP służący do generowania wyświetlanej nazwy grupy ownCloud.", "Base Group Tree" => "Drzewo bazy grup", "One Group Base DN per line" => "Jedna grupa bazy DN na linię", "Group Search Attributes" => "Grupa atrybutów wyszukaj", "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", @@ -65,11 +100,14 @@ $TRANSLATIONS = array( "User Home Folder Naming Rule" => "Reguły nazewnictwa folderu domowego użytkownika", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Pozostaw puste dla user name (domyślnie). W przeciwnym razie podaj atrybut LDAP/AD.", "Internal Username" => "Wewnętrzna nazwa użytkownika", +"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "Domyślnie, wewnętrzna nazwa użytkownika zostanie utworzona z atrybutu UUID, ang. Universally unique identifier - Unikalny identyfikator użytkownika. To daje pewność, że nazwa użytkownika jest niepowtarzalna, a znaki nie muszą być konwertowane. Wewnętrzna nazwa użytkownika dopuszcza jedynie znaki: [ a-zA-Z0-9_.@- ]. Pozostałe znaki zamieniane są na ich odpowiedniki ASCII lub po prostu pomijane. W przypadku, gdy nazwa się powtarza na końcu jest dodawana / zwiększana cyfra. Wewnętrzna nazwa użytkownika służy do wewnętrznej identyfikacji użytkownika. Jest to również domyślna nazwa folderu domowego użytkownika. Jest to również część zdalnego adresu URL, na przykład dla wszystkich usług *DAV. Dzięki temu ustawieniu można nadpisywać domyślne zachowanie aplikacji. Aby osiągnąć podobny efekt jak przed ownCloud 5 wpisz atrybut nazwy użytkownika w poniższym polu. Pozostaw puste dla domyślnego zachowania. Zmiany będą miały wpływ tylko na nowo przypisanych (dodanych) użytkowników LDAP.", "Internal Username Attribute:" => "Wewnętrzny atrybut nazwy uzżytkownika:", "Override UUID detection" => "Zastąp wykrywanie UUID", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "Domyślnie, atrybut UUID jest wykrywany automatycznie. Atrybut UUID jest używany do niepodważalnej identyfikacji użytkowników i grup LDAP. Również wewnętrzna nazwa użytkownika zostanie stworzona na bazie UUID, jeśli nie zostanie podana powyżej. Możesz nadpisać to ustawienie i użyć atrybutu wedle uznania. Musisz się jednak upewnić, że atrybut ten może zostać pobrany zarówno dla użytkowników, jak i grup i jest unikalny. Pozostaw puste dla domyślnego zachowania. Zmiany będą miały wpływ tylko na nowo przypisanych (dodanych) użytkowników i grupy LDAP.", "UUID Attribute for Users:" => "Atrybuty UUID dla użytkowników:", "UUID Attribute for Groups:" => "Atrybuty UUID dla grup:", "Username-LDAP User Mapping" => "Mapowanie użytkownika LDAP", +"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "Nazwy użytkowników są używane w celu przechowywania i przypisywania (meta) danych. Aby dokładnie zidentyfikować i rozpoznać użytkowników, każdy użytkownik LDAP będzie miał wewnętrzną nazwę. To wymaga utworzenia przypisania nazwy użytkownika do użytkownika LDAP. Utworzona nazwa użytkownika jet przypisywana do UUID użytkownika LDAP. Dodatkowo DN jest również buforowany aby zmniejszyć interakcję z LDAP, ale nie jest używany do identyfikacji. Jeśli DN się zmieni, zmiany zostaną odnalezione. Wewnętrzny użytkownik jest używany we wszystkich przypadkach. Wyczyszczenie mapowań spowoduje pozostawienie wszędzie resztek informacji. Wyczyszczenie mapowań nie jest wrażliwe na konfigurację, wpływa ono na wszystkie konfiguracje LDAP! Nigdy nie czyść mapowań w środowisku produkcyjnym, tylko podczas testów lub w fazie eksperymentalnej. ", "Clear Username-LDAP User Mapping" => "Czyść Mapowanie użytkownika LDAP", "Clear Groupname-LDAP Group Mapping" => "Czyść Mapowanie nazwy grupy LDAP" ); diff --git a/apps/user_ldap/l10n/pt_BR.php b/apps/user_ldap/l10n/pt_BR.php index 559dc949bd..0c15694e3f 100644 --- a/apps/user_ldap/l10n/pt_BR.php +++ b/apps/user_ldap/l10n/pt_BR.php @@ -33,14 +33,14 @@ $TRANSLATIONS = array( "Save" => "Guardar", "Test Configuration" => "Teste de Configuração", "Help" => "Ajuda", -"Limit the access to %s to groups meeting this criteria:" => "Limitar o acesso a %s para grupos que coincidam com estes critérios:", +"Groups meeting these criteria are available in %s:" => "Grupos que satisfazem estes critérios estão disponíveis em %s:", "only those object classes:" => "apenas essas classes de objetos:", "only from those groups:" => "apenas a partir dos grupos:", "Edit raw filter instead" => "Editar filtro raw ao invéz", "Raw LDAP filter" => "Filtro LDAP Raw", "The filter specifies which LDAP groups shall have access to the %s instance." => "O filtro especifica quais grupos LDAP devem ter acesso à instância do %s.", "groups found" => "grupos encontrados", -"What attribute shall be used as login name:" => "O atributo deve ser usado como nome de login:", +"Users login with this attribute:" => "Usuários entrar com este atributo:", "LDAP Username:" => "Usuário LDAP:", "LDAP Email Address:" => "LDAP Endereço de E-mail:", "Other Attributes:" => "Outros atributos:", @@ -55,7 +55,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Para acesso anônimo, deixe DN e Senha vazios.", "One Base DN per line" => "Uma base DN por linha", "You can specify Base DN for users and groups in the Advanced tab" => "Você pode especificar DN Base para usuários e grupos na guia Avançada", -"Limit the access to %s to users meeting this criteria:" => "Limitar o acesso a %s para usuários que coincidam com estes critérios:", +"Limit %s access to users meeting these criteria:" => "Limitar o acesso %s para usuários que satisfazem esses critérios:", "The filter specifies which LDAP users shall have access to the %s instance." => "O filtro especifica quais usuários LDAP devem ter acesso à instância do %s.", "users found" => "usuários encontrados", "Back" => "Voltar", @@ -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", @@ -88,6 +88,10 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Um grupo-base DN por linha", "Group Search Attributes" => "Atributos de Busca de Grupo", "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 89c37358b6..368eee1f12 100644 --- a/apps/user_ldap/l10n/pt_PT.php +++ b/apps/user_ldap/l10n/pt_PT.php @@ -1,9 +1,14 @@ "Falhou a limpar os mapas", -"Failed to delete the server configuration" => "Erro ao eliminar as configurações do servidor", +"Failed to delete the server configuration" => "Erro ao eliminar a configuração do servidor", "The configuration is valid and the connection could be established!" => "A configuração está correcta e foi possível estabelecer a ligação!", "The configuration is valid, but the Bind failed. Please check the server settings and credentials." => "A configuração está correcta, mas não foi possível estabelecer o \"laço\", por favor, verifique as configurações do servidor e as credenciais.", +"The configuration is invalid. Please have a look at the logs for further details." => "A configuração é inválida. Por favor, veja o log do ownCloud para mais detalhes.", +"No action specified" => "Nenhuma acção especificada", +"No configuration specified" => "Nenhuma configuração especificada", +"No data specified" => "Nenhuma data especificada", +" Could not set configuration %s" => "Não foi possível definir a configuração %s", "Deletion failed" => "Erro ao apagar", "Take over settings from recent server configuration?" => "Assumir as configurações da configuração do servidor mais recente?", "Keep settings?" => "Manter as definições?", @@ -11,16 +16,33 @@ $TRANSLATIONS = array( "mappings cleared" => "Mapas limpos", "Success" => "Sucesso", "Error" => "Erro", +"Configuration OK" => "Configuração OK", +"Configuration incorrect" => "Configuração incorreta", +"Configuration incomplete" => "Configuração incompleta", "Select groups" => "Seleccionar grupos", +"Select object classes" => "Selecionar classes de objetos", +"Select attributes" => "Selecionar atributos", "Connection test succeeded" => "Teste de conecção passado com sucesso.", "Connection test failed" => "Erro no teste de conecção.", "Do you really want to delete the current Server Configuration?" => "Deseja realmente apagar as configurações de servidor actuais?", "Confirm Deletion" => "Confirmar a operação de apagar", -"_%s group found_::_%s groups found_" => array("",""), -"_%s user found_::_%s users found_" => array("",""), +"_%s group found_::_%s groups found_" => array("%s grupo encontrado","%s grupos encontrados"), +"_%s user found_::_%s users found_" => array("%s utilizador encontrado","%s utilizadores encontrados"), +"Invalid Host" => "Hospedeiro Inválido", +"Could not find the desired feature" => "Não se encontrou a função desejada", "Save" => "Guardar", "Test Configuration" => "Testar a configuração", "Help" => "Ajuda", +"only those object classes:" => "apenas essas classes de objetos:", +"only from those groups:" => "apenas desses grupos:", +"Edit raw filter instead" => "Editar filtro raw em vez disso", +"Raw LDAP filter" => "Filtro LDAP Raw", +"The filter specifies which LDAP groups shall have access to the %s instance." => "O filtro especifica quais grupos LDAP devem ter acesso à instância %s.", +"groups found" => "grupos encontrados", +"LDAP Username:" => "Nome de utilizador LDAP:", +"LDAP Email Address:" => "Endereço de correio eletrónico LDAP:", +"Other Attributes:" => "Outros Atributos:", +"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "Define o filtro a aplicar, quando se tenta uma sessão. %%uid substitui o nome de utilizador na ação de início de sessão. Exemplo: \"uid=%%uid\"", "Add Server Configuration" => "Adicionar configurações do servidor", "Host" => "Anfitrião", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "Pode omitir o protocolo, excepto se necessitar de SSL. Neste caso, comece com ldaps://", @@ -31,8 +53,11 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Para acesso anónimo, deixe DN e a Palavra-passe vazios.", "One Base DN per line" => "Uma base DN por linho", "You can specify Base DN for users and groups in the Advanced tab" => "Pode especificar o ND Base para utilizadores e grupos no separador Avançado", +"Limit %s access to users meeting these criteria:" => "Limitar o acesso a %s de utilizadores com estes critérios:", +"users found" => "utilizadores encontrados", "Back" => "Voltar", "Continue" => "Continuar", +"Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "Aviso: A aplicação user_ldap e user_webdavauth são incompativeis. A aplicação pode tornar-se instável. Por favor, peça ao seu administrador para desactivar uma das aplicações.", "Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Aviso: O módulo PHP LDAP não está instalado, logo não irá funcionar. Por favor peça ao administrador para o instalar.", "Connection Settings" => "Definições de ligação", "Configuration Active" => "Configuração activa", @@ -41,17 +66,19 @@ $TRANSLATIONS = array( "Give an optional backup host. It must be a replica of the main LDAP/AD server." => "Forneça um servidor (anfitrião) de backup. Deve ser uma réplica do servidor principal de LDAP/AD ", "Backup (Replica) Port" => "Porta do servidor de backup (Replica)", "Disable Main Server" => "Desactivar servidor principal", -"Case insensitve LDAP server (Windows)" => "Servidor LDAP (Windows) não sensível a maiúsculas.", +"Only connect to the replica server." => "Ligar apenas ao servidor de réplicas.", "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.", "Directory Settings" => "Definições de directorias", "User Display Name Field" => "Mostrador do nome de utilizador.", +"The LDAP attribute to use to generate the user's display name." => "Atributo LDAP para gerar o nome de utilizador do ownCloud.", "Base User Tree" => "Base da árvore de utilizadores.", "One User Base DN per line" => "Uma base de utilizador DN por linha", "User Search Attributes" => "Utilizar atributos de pesquisa", "Optional; one attribute per line" => "Opcional; Um atributo por linha", "Group Display Name Field" => "Mostrador do nome do grupo.", +"The LDAP attribute to use to generate the groups's display name." => "Atributo LDAP para gerar o nome do grupo do ownCloud.", "Base Group Tree" => "Base da árvore de grupos.", "One Group Base DN per line" => "Uma base de grupo DN por linha", "Group Search Attributes" => "Atributos de pesquisa de grupo", @@ -64,8 +91,11 @@ $TRANSLATIONS = array( "User Home Folder Naming Rule" => "Regra da pasta inicial do utilizador", "Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Deixe vazio para nome de utilizador (padrão). De outro modo, especifique um atributo LDAP/AD.", "Internal Username" => "Nome de utilizador interno", +"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "Por padrão o nome de utilizador interno vai ser criado através do atributo UUID. Desta forma é assegurado que o nome é único e os caracteres não necessitam de serem convertidos. O nome interno tem a restrição de que apenas estes caracteres são permitidos: [ a-zA-Z0-9_.@- ]. Outros caracteres são substituídos pela sua correspondência ASCII ou simplesmente omitidos. Mesmo assim, quando for detetado uma colisão irá ser acrescentado um número. O nome interno é usado para identificar o utilizador internamente. É também o nome utilizado para a pasta inicial no ownCloud. É também parte de URLs remotos, como por exemplo os serviços *DAV. Com esta definição, o comportamento padrão é pode ser sobreposto. Para obter o mesmo comportamento antes do ownCloud 5 introduza o atributo do nome no campo seguinte. Deixe vazio para obter o comportamento padrão. As alterações apenas serão feitas para utilizadores mapeados (adicionados) LDAP.", "Internal Username Attribute:" => "Atributo do nome de utilizador interno", "Override UUID detection" => "Passar a detecção do UUID", +"UUID Attribute for Users:" => "Atributo UUID para utilizadores:", +"UUID Attribute for Groups:" => "Atributo UUID para grupos:", "Username-LDAP User Mapping" => "Mapeamento do utilizador LDAP", "Clear Username-LDAP User Mapping" => "Limpar mapeamento do utilizador-LDAP", "Clear Groupname-LDAP Group Mapping" => "Limpar o mapeamento do nome de grupo LDAP" diff --git a/apps/user_ldap/l10n/ro.php b/apps/user_ldap/l10n/ro.php index 0214be3f78..0a91abe29c 100644 --- a/apps/user_ldap/l10n/ro.php +++ b/apps/user_ldap/l10n/ro.php @@ -1,12 +1,29 @@ "Configuraţia este valida şi s-a stabilit conectarea", +"No action specified" => "Nu este specificata nici o acţiune ", +"No configuration specified" => "Nu este specificata nici o configurare ", "Deletion failed" => "Ștergerea a eșuat", +"Keep settings?" => "Păstraţi setările ?", +"Cannot add server configuration" => "Nu se poate adăuga configuraţia serverului ", "Success" => "Succes", "Error" => "Eroare", +"Configuration OK" => "Configuraţie valida", +"Configuration incorrect" => "Configuraţie incorecta ", +"Configuration incomplete" => "Configuraţie incompleta ", +"Select groups" => "Selectaţi grupuri ", +"Select attributes" => "Selectaţi caracteristici", +"Connection test succeeded" => "Testul de conectare a reuşit ", +"Connection test failed" => "Testul de conectare a eşuat ", +"Do you really want to delete the current Server Configuration?" => "Sunteţi sigur ca vreţi sa ştergeţi configuraţia actuala a serverului ?", +"Confirm Deletion" => "Confirmaţi Ştergerea ", "_%s group found_::_%s groups found_" => array("","",""), "_%s user found_::_%s users found_" => array("","",""), "Save" => "Salvează", +"Test Configuration" => "Configurare test", "Help" => "Ajutor", +"Other Attributes:" => "Alte caracteristici :", +"Add Server Configuration" => "Adăugaţi Configuraţia Serverului", "Host" => "Gazdă", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "Puteți omite protocolul, decât dacă folosiți SSL. Atunci se începe cu ldaps://", "Port" => "Portul", @@ -16,12 +33,16 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Pentru acces anonim, lăsați DN și Parolă libere.", "One Base DN per line" => "Un Base DN pe linie", "You can specify Base DN for users and groups in the Advanced tab" => "Puteți să specificați DN de bază pentru utilizatori și grupuri în fila Avansat", +"users found" => "Utilizatori găsiţi ", "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)", +"Connection Settings" => "Setările de conexiune", +"Configuration Active" => "Configuraţie activa ", +"Disable Main Server" => "Dezactivaţi serverul principal", "Turn off SSL certificate validation." => "Oprește validarea certificatelor SSL ", "in seconds. A change empties the cache." => "în secunde. O schimbare curăță memoria tampon.", +"Directory Settings" => "Setările directorului", "User Display Name Field" => "Câmpul cu numele vizibil al utilizatorului", "Base User Tree" => "Arborele de bază al Utilizatorilor", "One User Base DN per line" => "Un User Base DN pe linie", @@ -29,7 +50,9 @@ $TRANSLATIONS = array( "Base Group Tree" => "Arborele de bază al Grupurilor", "One Group Base DN per line" => "Un Group Base DN pe linie", "Group-Member association" => "Asocierea Grup-Membru", +"Special Attributes" => "Caracteristici speciale ", "in bytes" => "în octeți", -"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Lăsați gol pentru numele de utilizator (implicit). În caz contrar, specificați un atribut LDAP / AD." +"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Lăsați gol pentru numele de utilizator (implicit). În caz contrar, specificați un atribut LDAP / AD.", +"Internal Username" => "Nume utilizator intern" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"; diff --git a/apps/user_ldap/l10n/ru.php b/apps/user_ldap/l10n/ru.php index 7b9cf8ceb5..e719f01c37 100644 --- a/apps/user_ldap/l10n/ru.php +++ b/apps/user_ldap/l10n/ru.php @@ -33,14 +33,12 @@ $TRANSLATIONS = array( "Save" => "Сохранить", "Test Configuration" => "Проверить конфигурацию", "Help" => "Помощь", -"Limit the access to %s to groups meeting this criteria:" => "Ограничить доступ к %s группам, удовлетворяющим этому критерию:", "only those object classes:" => "только эти объектные классы", "only from those groups:" => "только из этих групп", "Edit raw filter instead" => "Редактировать исходный фильтр", "Raw LDAP filter" => "Исходный LDAP фильтр", "The filter specifies which LDAP groups shall have access to the %s instance." => "Этот фильтр определяет, какие LDAP группы должны иметь доступ к %s.", "groups found" => "групп найдено", -"What attribute shall be used as login name:" => "Какой атрибут должен быть использован для логина:", "LDAP Username:" => "Имя пользователя LDAP", "LDAP Email Address:" => "LDAP адрес электронной почты:", "Other Attributes:" => "Другие атрибуты:", @@ -55,7 +53,7 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Для анонимного доступа оставьте DN и пароль пустыми.", "One Base DN per line" => "По одной базе поиска (Base DN) в строке.", "You can specify Base DN for users and groups in the Advanced tab" => "Вы можете задать Base DN для пользователей и групп на вкладке \"Расширенное\"", -"Limit the access to %s to users meeting this criteria:" => "Ограничить доступ к %s пользователям, удовлетворяющим этому критерию:", +"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" => "Назад", @@ -70,7 +68,7 @@ $TRANSLATIONS = array( "Backup (Replica) Port" => "Порт резервного сервера", "Disable Main Server" => "Отключить главный сервер", "Only connect to the replica server." => "Подключаться только к серверу-реплике.", -"Case insensitve LDAP server (Windows)" => "Нечувствительный к регистру сервер LDAP (Windows)", +"Case insensitive 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" => "Кэш времени жизни", @@ -99,7 +97,7 @@ $TRANSLATIONS = array( "By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "По умолчанию внутреннее имя пользователя будет создано из атрибута UUID. Таким образом имя пользователя становится уникальным и не требует конвертации символов. Внутреннее имя пользователя может состоять только из следующих символов: [ a-zA-Z0-9_.@- ]. Остальные символы замещаются соответствиями из таблицы ASCII или же просто пропускаются. При совпадении к имени будет добавлено или увеличено число. Внутреннее имя пользователя используется для внутренней идентификации пользователя. Также оно является именем по умолчанию для папки пользователя в ownCloud. Оно также является частью URL, к примеру, для всех сервисов *DAV. С помощью данной настройки можно изменить поведение по умолчанию. Чтобы достичь поведения, как было до ownCloud 5, введите атрибут отображаемого имени пользователя в этом поле. Оставьте его пустым для режима по умолчанию. Изменения будут иметь эффект только для новых подключенных (добавленных) пользователей LDAP.", "Internal Username Attribute:" => "Атрибут для внутреннего имени:", "Override UUID detection" => "Переопределить нахождение UUID", -"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "По умолчанию ownCloud определяет атрибут UUID автоматически. Этот атрибут используется для того, чтобы достоверно индентифицировать пользователей и группы LDAP. Также на основании атрибута UUID создается внутреннее имя пользователя, если выше не указано иначе. Вы можете переопределить эту настройку и указать свой атрибут по выбору. Вы должны удостовериться, что выбранный вами атрибут может быть выбран для пользователей и групп, а также то, что он уникальный. Оставьте поле пустым для поведения по умолчанию. Изменения вступят в силу только для новых подключенных (добавленных) пользователей и групп LDAP.", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "По умолчанию ownCloud определяет атрибут UUID автоматически. Этот атрибут используется для того, чтобы достоверно идентифицировать пользователей и группы LDAP. Также на основании атрибута UUID создается внутреннее имя пользователя, если выше не указано иначе. Вы можете переопределить эту настройку и указать свой атрибут по выбору. Вы должны удостовериться, что выбранный вами атрибут может быть выбран для пользователей и групп, а также то, что он уникальный. Оставьте поле пустым для поведения по умолчанию. Изменения вступят в силу только для новых подключенных (добавленных) пользователей и групп LDAP.", "UUID Attribute for Users:" => "UUID-атрибуты для пользователей:", "UUID Attribute for Groups:" => "UUID-атрибуты для групп:", "Username-LDAP User Mapping" => "Соответствия Имя-Пользователь LDAP", diff --git a/apps/user_ldap/l10n/sk_SK.php b/apps/user_ldap/l10n/sk_SK.php index 850fce24c4..fdcb4ea81b 100644 --- a/apps/user_ldap/l10n/sk_SK.php +++ b/apps/user_ldap/l10n/sk_SK.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "mappings cleared" => "mapovanie vymazané", "Success" => "Úspešné", "Error" => "Chyba", -"Configuration OK" => "Konfigurácia je vporiadku", +"Configuration OK" => "Konfigurácia je v poriadku", "Configuration incorrect" => "Nesprávna konfigurácia", "Configuration incomplete" => "Nekompletná konfigurácia", "Select groups" => "Vybrať skupinu", @@ -33,21 +33,21 @@ $TRANSLATIONS = array( "Save" => "Uložiť", "Test Configuration" => "Test nastavenia", "Help" => "Pomoc", -"Limit the access to %s to groups meeting this criteria:" => "Obmedziť prístup %s do skupiny, ktoré spĺňajú tieto kritériá:", +"Groups meeting these criteria are available in %s:" => "Skupiny spĺňajúce tieto kritériá sú k dispozícii v %s:", "only those object classes:" => "len tieto triedy objektov:", "only from those groups:" => "len z týchto skupín:", "Edit raw filter instead" => "Miesto pre úpravu raw filtra", "Raw LDAP filter" => "Raw LDAP filter", "The filter specifies which LDAP groups shall have access to the %s instance." => "Tento filter LDAP určuje, ktoré skupiny budú mať prístup k %s inštancii.", "groups found" => "nájdené skupiny", -"What attribute shall be used as login name:" => "Ako prihlasovacie meno použiť atribút:", +"Users login with this attribute:" => "Používateľov prihlásiť pomocou tohto atribútu:", "LDAP Username:" => "LDAP používateľské meno:", "LDAP Email Address:" => "LDAP emailová adresa:", "Other Attributes:" => "Iné atribúty:", -"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "Určuje použitý filter, pri pokuse o prihlásenie. %%uid nahradzuje používateľské meno v činnosti prihlásenia. Napríklad: \"uid=%%uid\"", +"Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: \"uid=%%uid\"" => "Určuje použitý filter, pri pokuse o prihlásenie. %%uid nahrádza používateľské meno v činnosti prihlásenia. Napríklad: \"uid=%%uid\"", "Add Server Configuration" => "Pridať nastavenia servera.", "Host" => "Hostiteľ", -"You can omit the protocol, except you require SSL. Then start with ldaps://" => "Môžete vynechať protokol, s výnimkou požadovania SSL. Vtedy začnite s ldaps://", +"You can omit the protocol, except you require SSL. Then start with ldaps://" => "Môžete vynechať protokol, okrem prípadu, kedy sa vyžaduje SSL. Vtedy začnite s ldaps://", "Port" => "Port", "User DN" => "Používateľské 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 klientského používateľa, ku ktorému tvoríte väzbu, napr. uid=agent,dc=example,dc=com. Pre anonymný prístup ponechajte údaje DN a Heslo prázdne.", @@ -55,13 +55,13 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Pre anonymný prístup ponechajte údaje DN a Heslo prázdne.", "One Base DN per line" => "Jedno základné DN na riadok", "You can specify Base DN for users and groups in the Advanced tab" => "V rozšírenom nastavení môžete zadať základné DN pre používateľov a skupiny", -"Limit the access to %s to users meeting this criteria:" => "Obmedziť prístup k %s na používateľov, ktorí spĺňajú tieto kritériá:", +"Limit %s access to users meeting these criteria:" => "Obmedziť %s prístup na používateľov spĺňajúcich tieto kritériá:", "The filter specifies which LDAP users shall have access to the %s instance." => "Tento filter LDAP určuje, ktorí používatelia majú prístup k %s inštancii.", "users found" => "nájdení používatelia", "Back" => "Späť", "Continue" => "Pokračovať", "Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behavior. Please ask your system administrator to disable one of them." => "Upozornenie: Aplikácie user_ldap a user_webdavauth sú navzájom nekompatibilné. Môžete zaznamenať neočakávané správanie. Požiadajte prosím vášho systémového administrátora pre zakázanie jedného z nich.", -"Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Upozornenie: nie je nainštalovaný LDAP modul pre PHP, backend vrstva nebude fungovať. Požádejte administrátora systému aby ho nainštaloval.", +"Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "Upozornenie: nie je nainštalovaný LDAP modul pre PHP, backend vrstva nebude fungovať. Požiadajte administrátora systému, aby ho nainštaloval.", "Connection Settings" => "Nastavenie pripojenia", "Configuration Active" => "Nastavenia sú aktívne ", "When unchecked, this configuration will be skipped." => "Ak nie je zaškrtnuté, nastavenie bude preskočené.", @@ -70,13 +70,13 @@ $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)", +"Case insensitive LDAP server (Windows)" => "LDAP server je citlivý na veľkosť písmen (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 v medzipamäti", +"Cache Time-To-Live" => "Životnosť objektov vo vyrovnávacej pamäti", "in seconds. A change empties the cache." => "v sekundách. Zmena vyprázdni vyrovnávaciu pamäť.", -"Directory Settings" => "Nastavenie priečinka", -"User Display Name Field" => "Pole pre zobrazenie mena používateľa", +"Directory Settings" => "Nastavenia priečinka", +"User Display Name Field" => "Pole pre zobrazované meno používateľa", "The LDAP attribute to use to generate the user's display name." => "Atribút LDAP použitý na vygenerovanie zobrazovaného mena používateľa. ", "Base User Tree" => "Základný používateľský strom", "One User Base DN per line" => "Jedna používateľská základná DN na riadok", @@ -88,22 +88,24 @@ $TRANSLATIONS = array( "One Group Base DN per line" => "Jedna skupinová základná DN na riadok", "Group Search Attributes" => "Atribúty vyhľadávania skupín", "Group-Member association" => "Priradenie člena skupiny", +"Nested Groups" => "Vnorené skupiny", +"When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)" => "Ak je zapnuté, tak je možné používať skupiny, ktoré obsahujú iné skupiny. (Funguje, len ak atribút člena skupiny obsahuje DN.)", "Special Attributes" => "Špeciálne atribúty", "Quota Field" => "Pole kvóty", "Quota Default" => "Predvolená kvóta", "in bytes" => "v bajtoch", "Email Field" => "Pole emailu", "User Home Folder Naming Rule" => "Pravidlo pre nastavenie názvu používateľského priečinka dát", -"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Nechajte prázdne pre používateľské meno (predvolené). Inak uveďte atribút LDAP/AD.", +"Leave empty for user name (default). Otherwise, specify an LDAP/AD attribute." => "Nechajte prázdne pre používateľské meno (predvolené). Inak uveďte atribút z LDAP/AD.", "Internal Username" => "Interné používateľské meno", -"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "V predvolenom nastavení bude interné používateľské meno vytvorené z UUID atribútu. Zabezpečí sa to, že používateľské meno bude jedinečné a znaky nemusia byť prevedené. Interné meno má obmedzenie, iba tieto znaky sú povolené: [a-zA-Z0-9_ @ -.]. Ostatné znaky sú nahradené ich ASCII alebo jednoducho vynechané. Pri kolíziách používateľských mien bude číslo pridané / odobrané. Interné používateľské meno sa používa na internú identifikáciu používateľa. Je tiež predvoleným názvom používateľského domovského priečinka v ownCloud. Je tiež súčasťou URL pre vzdialený prístup, napríklad pre všetky služby * DAV. S týmto nastavením sa dá prepísať predvolené správanie. Pre dosiahnutie podobného správania sa ako pred verziou ownCloud 5 zadajte atribút zobrazenia používateľského mena v tomto poli. Ponechajte prázdne pre predvolené správanie. Zmeny budú mať vplyv iba na novo namapovaných (pridaných) LDAP používateľov.", +"By default the internal username will be created from the UUID attribute. It makes sure that the username is unique and characters do not need to be converted. The internal username has the restriction that only these characters are allowed: [ a-zA-Z0-9_.@- ]. Other characters are replaced with their ASCII correspondence or simply omitted. On collisions a number will be added/increased. The internal username is used to identify a user internally. It is also the default name for the user home folder. It is also a part of remote URLs, for instance for all *DAV services. With this setting, the default behavior can be overridden. To achieve a similar behavior as before ownCloud 5 enter the user display name attribute in the following field. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users." => "V predvolenom nastavení bude interné používateľské meno vytvorené z UUID atribútu. Zabezpečí sa to, že používateľské meno bude jedinečné a znaky nemusia byť prevedené. Interné meno má obmedzenie, iba tieto znaky sú povolené: [a-zA-Z0-9_ @ -.]. Ostatné znaky sú nahradené ich ASCII alebo jednoducho vynechané. Pri kolíziách používateľských mien bude číslo pridané / odobrané. Interné používateľské meno sa používa na internú identifikáciu používateľa. Je tiež predvoleným názvom používateľského domovského priečinka v ownCloud. Je tiež súčasťou URL pre vzdialený prístup, napríklad pre všetky služby *DAV. S týmto nastavením sa dá prepísať predvolené správanie. Pre dosiahnutie podobného správania sa ako pred verziou ownCloud 5 zadajte atribút zobrazenia používateľského mena v tomto poli. Ponechajte prázdne pre predvolené správanie. Zmeny budú mať vplyv iba na novo namapovaných (pridaných) LDAP používateľov.", "Internal Username Attribute:" => "Atribút interného používateľského mena:", "Override UUID detection" => "Prepísať UUID detekciu", -"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "V predvolenom nastavení je UUID atribút detekovaný automaticky. UUID atribút je použitý na jedinečnú identifikáciu používateľov a skupín z LDAP. Naviac je na základe UUID vytvorené tiež interné použivateľské meno, ak nie je nastavené inak. Môžete predvolené nastavenie prepísať a použiť atribút ktorý si sami zvolíte. Musíte sa ale ubezpečiť, že atribút ktorý vyberiete bude uvedený pri použivateľoch, aj pri skupinách a je jedinečný. Ponechajte prázdne pre predvolené správanie. Zmena bude mať vplyv len na novo namapovaných (pridaných) používateľov a skupiny z LDAP.", +"By default, the UUID attribute is automatically detected. The UUID attribute is used to doubtlessly identify LDAP users and groups. Also, the internal username will be created based on the UUID, if not specified otherwise above. You can override the setting and pass an attribute of your choice. You must make sure that the attribute of your choice can be fetched for both users and groups and it is unique. Leave it empty for default behavior. Changes will have effect only on newly mapped (added) LDAP users and groups." => "V predvolenom nastavení je UUID atribút detekovaný automaticky. UUID atribút je použitý na jedinečnú identifikáciu používateľov a skupín z LDAP. Naviac je na základe UUID vytvorené tiež interné používateľské meno, ak nie je nastavené inak. Môžete predvolené nastavenie prepísať a použiť atribút ktorý si sami zvolíte. Musíte sa ale ubezpečiť, že atribút ktorý vyberiete bude uvedený pri používateľoch, aj pri skupinách a je jedinečný. Ponechajte prázdne pre predvolené správanie. Zmena bude mať vplyv len na novo namapovaných (pridaných) používateľov a skupiny z LDAP.", "UUID Attribute for Users:" => "UUID atribút pre používateľov:", "UUID Attribute for Groups:" => "UUID atribút pre skupiny:", "Username-LDAP User Mapping" => "Mapovanie názvov LDAP používateľských mien", -"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "Použivateľské mená sa používajú pre uchovávanie a priraďovanie (meta)dát. Pre správnu identifikáciu a rozpoznanie používateľov bude mať každý používateľ z LDAP interné používateľské meno. To je nevyhnutné pre namapovanie používateľských mien na používateľov v LDAP. Vytvorené používateľské meno je namapované na UUID používateľa v LDAP. Naviac je cachovaná DN pre obmedzenie interakcie s LDAP, ale nie je používaná pre identifikáciu. Ak sa DN zmení, bude to správne rozpoznané. Interné používateľské meno sa používa všade. Vyčistenie namapování vymaže zvyšky všade. Vyčistenie naviac nie je špecifické, bude mať vplyv na všetky LDAP konfigurácie! Nikdy nečistite namapovanie v produkčnom prostredí, len v testovacej alebo experimentálnej fáze.", +"Usernames are used to store and assign (meta) data. In order to precisely identify and recognize users, each LDAP user will have a internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." => "Používateľské mená sa používajú pre uchovávanie a priraďovanie (meta) dát. Pre správnu identifikáciu a rozpoznanie používateľov bude mať každý používateľ z LDAP interné používateľské meno. To je nevyhnutné pre namapovanie používateľských mien na používateľov v LDAP. Vytvorené používateľské meno je namapované na UUID používateľa v LDAP. Naviac je cachovaná DN pre obmedzenie interakcie s LDAP, ale nie je používaná pre identifikáciu. Ak sa DN zmení, bude to správne rozpoznané. Interné používateľské meno sa používa všade. Vyčistenie namapovaní vymaže zvyšky všade. Vyčistenie naviac nie je špecifické, bude mať vplyv na všetky LDAP konfigurácie! Nikdy nečistite namapovanie v produkčnom prostredí, len v testovacej alebo experimentálnej fáze.", "Clear Username-LDAP User Mapping" => "Zrušiť mapovanie LDAP používateľských mien", "Clear Groupname-LDAP Group Mapping" => "Zrušiť mapovanie názvov LDAP skupín" ); diff --git a/apps/user_ldap/l10n/sl.php b/apps/user_ldap/l10n/sl.php index b51c5bc7bb..54c91103a3 100644 --- a/apps/user_ldap/l10n/sl.php +++ b/apps/user_ldap/l10n/sl.php @@ -33,14 +33,12 @@ $TRANSLATIONS = array( "Save" => "Shrani", "Test Configuration" => "Preizkusne nastavitve", "Help" => "Pomoč", -"Limit the access to %s to groups meeting this criteria:" => "Omeji dostop %s do skupin glede na kriterij:", "only those object classes:" => "le razredi predmeta:", "only from those groups:" => "le iz skupin:", "Edit raw filter instead" => "Uredi surov filter", "Raw LDAP filter" => "Surovi filter LDAP", "The filter specifies which LDAP groups shall have access to the %s instance." => "Filter določa, katere skupine LDAP bodo imele dostop do %s.", "groups found" => "najdenih skupin", -"What attribute shall be used as login name:" => "Kateri atribut naj bo uporabljen kot prijavno ime:", "LDAP Username:" => "Uporabniško ime LDAP:", "LDAP Email Address:" => "Elektronski naslov LDAP:", "Other Attributes:" => "Drugi atributi:", @@ -55,7 +53,6 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Za brezimni dostop naj bosta polji imena in gesla prazni.", "One Base DN per line" => "Eno osnovno enolično ime na vrstico", "You can specify Base DN for users and groups in the Advanced tab" => "Osnovno enolično ime za uporabnike in skupine lahko določite v zavihku naprednih možnosti.", -"Limit the access to %s to users meeting this criteria:" => "Omeji dostop do %s uporabnikom, za katere velja kriterij:", "The filter specifies which LDAP users shall have access to the %s instance." => "Filter določa, kateri uporabniki LDAP bodo imeli dostop do %s.", "users found" => "najdenih uporabnikov", "Back" => "Nazaj", @@ -70,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", @@ -88,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 0f18ac0235..03ff204bbc 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 d2ce2cf08b..fb016fdd17 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/su.php b/apps/user_ldap/l10n/su.php new file mode 100644 index 0000000000..bba52d53a1 --- /dev/null +++ b/apps/user_ldap/l10n/su.php @@ -0,0 +1,6 @@ + array(""), +"_%s user found_::_%s users found_" => array("") +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_ldap/l10n/sv.php b/apps/user_ldap/l10n/sv.php index 62beec274e..2a4f8b1965 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", -"Limit the access to %s to groups meeting this criteria:" => "Begränsa åtkomsten till %s till grupper som möter följande kriterie:", +"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", -"What attribute shall be used as login name:" => "Vilket attribut ska användas som login namn:", +"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,7 +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 the access to %s to users meeting this criteria:" => "Begränsa åtkomsten till %s till användare som möter följande kriterie:", +"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", @@ -68,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", @@ -86,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_IN.php b/apps/user_ldap/l10n/ta_IN.php new file mode 100644 index 0000000000..3a1e002311 --- /dev/null +++ b/apps/user_ldap/l10n/ta_IN.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/ta_LK.php b/apps/user_ldap/l10n/ta_LK.php index c7efcf0589..27a3068f96 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/te.php b/apps/user_ldap/l10n/te.php index ad3ffb1c5e..e154c06873 100644 --- a/apps/user_ldap/l10n/te.php +++ b/apps/user_ldap/l10n/te.php @@ -5,6 +5,7 @@ $TRANSLATIONS = array( "_%s user found_::_%s users found_" => array("",""), "Save" => "భద్రపరచు", "Help" => "సహాయం", -"Password" => "సంకేతపదం" +"Password" => "సంకేతపదం", +"Continue" => "కొనసాగించు" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_ldap/l10n/th_TH.php b/apps/user_ldap/l10n/th_TH.php index 2202a2f0a8..1c6dbe0473 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 8299c5feca..48e39c8523 100644 --- a/apps/user_ldap/l10n/tr.php +++ b/apps/user_ldap/l10n/tr.php @@ -33,61 +33,65 @@ $TRANSLATIONS = array( "Save" => "Kaydet", "Test Configuration" => "Test Yapılandırması", "Help" => "Yardım", -"Limit the access to %s to groups meeting this criteria:" => "%s erişimini, şu kriterle eşleşen gruplara sınırla:", +"Groups meeting these criteria are available in %s:" => "Bu kriterle eşleşen gruplar %s içinde mevcut:", "only those object classes:" => "sadece bu nesne sınıflarına:", "only from those groups:" => "sadece bu gruplardan:", "Edit raw filter instead" => "Bunun yerine ham filtreyi düzenle", "Raw LDAP filter" => "Ham LDAP filtresi", "The filter specifies which LDAP groups shall have access to the %s instance." => "Filtre, %s örneğine erişmesi gereken LDAP gruplarını belirtir.", "groups found" => "grup bulundu", -"What attribute shall be used as login name:" => "Oturum ismi olarak hangi nitelik kullanılmalı:", +"Users login with this attribute:" => "Bu nitelikle oturum açan kullanıcılar:", "LDAP Username:" => "LDAP Kullanıcı Adı:", "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. ", -"Limit the access to %s to users meeting this criteria:" => "%s erişimini, şu kriterle eşleşen kullanıcılara sınırla:", +"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 e87348ec44..5f4db6d5a0 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 f1f069cc4d..21b9783897 100644 --- a/apps/user_ldap/l10n/vi.php +++ b/apps/user_ldap/l10n/vi.php @@ -17,10 +17,10 @@ $TRANSLATIONS = array( "For anonymous access, leave DN and Password empty." => "Cho phép truy cập nặc danh , DN và mật khẩu trống.", "You can specify Base DN for users and groups in the Advanced tab" => "Bạn có thể chỉ định DN cơ bản cho người dùng và các nhóm trong tab Advanced", "Back" => "Trở lại", +"Continue" => "Tiếp tục", "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 f1a3625bf3..d56f394f64 100644 --- a/apps/user_ldap/l10n/zh_CN.php +++ b/apps/user_ldap/l10n/zh_CN.php @@ -32,6 +32,7 @@ $TRANSLATIONS = array( "One Base DN per line" => "每行一个基本判别名", "You can specify Base DN for users and groups in the Advanced tab" => "您可以在高级选项卡里为用户和组指定Base DN", "Back" => "返回", +"Continue" => "继续", "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" => "连接设置", "Configuration Active" => "现行配置", @@ -40,7 +41,7 @@ $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)", +"Only connect to the replica server." => "只能连接到复制服务器", "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 a7ae04cd16..a0975b9223 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/access.php b/apps/user_ldap/lib/access.php index b7e4023dd7..712407505f 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -63,7 +63,6 @@ class Access extends LDAPUtility { return false; } //all or nothing! otherwise we get in trouble with. - $this->initPagedSearch($filter, array($dn), $attr, 99999, 0); $dn = $this->DNasBaseParameter($dn); $rr = @$this->ldap->read($cr, $dn, $filter, array($attr)); if(!$this->ldap->isResource($rr)) { @@ -434,12 +433,27 @@ class Access extends LDAPUtility { $ocname = $this->dn2ocname($ldapObject['dn'], $nameByLDAP, $isUsers); if($ocname) { $ownCloudNames[] = $ocname; + if($isUsers) { + //cache the user names so it does not need to be retrieved + //again later (e.g. sharing dialogue). + $this->cacheUserDisplayName($ocname, $nameByLDAP); + } } continue; } return $ownCloudNames; } + /** + * @brief caches the user display name + * @param string the internal owncloud username + * @param string the display name + */ + public function cacheUserDisplayName($ocname, $displayName) { + $cacheKeyTrunk = 'getDisplayName'; + $this->connection->writeToCache($cacheKeyTrunk.$ocname, $displayName); + } + /** * @brief creates a unique name for internal ownCloud use for users. Don't call it directly. * @param $name the display name of the object @@ -659,7 +673,7 @@ class Access extends LDAPUtility { * @param string $filter */ public function countUsers($filter, $attr = array('dn'), $limit = null, $offset = null) { - return $this->count($filter, $this->connection->ldapBaseGroups, $attr, $limit, $offset); + return $this->count($filter, $this->connection->ldapBaseUsers, $attr, $limit, $offset); } /** @@ -707,6 +721,9 @@ class Access extends LDAPUtility { $linkResources = array_pad(array(), count($base), $cr); $sr = $this->ldap->search($linkResources, $base, $filter, $attr); $error = $this->ldap->errno($cr); + if ($pagedSearchOK) { + $this->ldap->controlPagedResult($cr, 999999, false, ""); + } if(!is_array($sr) || $error !== 0) { \OCP\Util::writeLog('user_ldap', 'Error when searching: '.$this->ldap->error($cr). @@ -775,22 +792,47 @@ class Access extends LDAPUtility { */ private function count($filter, $base, $attr = null, $limit = null, $offset = null, $skipHandling = false) { \OCP\Util::writeLog('user_ldap', 'Count filter: '.print_r($filter, true), \OCP\Util::DEBUG); - $search = $this->executeSearch($filter, $base, $attr, $limit, $offset); - if($search === false) { - return false; - } - list($sr, $pagedSearchOK) = $search; - $cr = $this->connection->getConnectionResource(); - $counter = 0; - foreach($sr as $key => $res) { - $count = $this->ldap->countEntries($cr, $res); - if($count !== false) { - $counter += $count; - } + + if(is_null($limit)) { + $limit = $this->connection->ldapPagingSize; } - $this->processPagedSearchStatus($sr, $filter, $base, $counter, $limit, + $counter = 0; + $count = null; + $cr = $this->connection->getConnectionResource(); + + do { + $continue = false; + $search = $this->executeSearch($filter, $base, $attr, + $limit, $offset); + if($search === false) { + return $counter > 0 ? $counter : false; + } + list($sr, $pagedSearchOK) = $search; + + $count = $this->countEntriesInSearchResults($sr, $limit, $continue); + $counter += $count; + + $this->processPagedSearchStatus($sr, $filter, $base, $count, $limit, $offset, $pagedSearchOK, $skipHandling); + $offset += $limit; + } while($continue); + + return $counter; + } + + private function countEntriesInSearchResults($searchResults, $limit, + &$hasHitLimit) { + $cr = $this->connection->getConnectionResource(); + $count = 0; + + foreach($searchResults as $res) { + $count = intval($this->ldap->countEntries($cr, $res)); + $counter += $count; + if($count === $limit) { + $hasHitLimit = true; + } + } return $counter; } @@ -891,7 +933,7 @@ class Access extends LDAPUtility { //we slice the findings, when //a) paged search insuccessful, though attempted //b) no paged search, but limit set - if((!$this->pagedSearchedSuccessful + if((!$this->getPagedSearchResultState() && $pagedSearchOK) || ( !$pagedSearchOK @@ -923,8 +965,8 @@ class Access extends LDAPUtility { /** * @brief escapes (user provided) parts for LDAP filter - * @param String $input, the provided value - * @returns the escaped string + * @param string $input, the provided value + * @return the escaped string */ public function escapeFilterPart($input) { $search = array('*', '\\', '(', ')'); @@ -1064,8 +1106,8 @@ class Access extends LDAPUtility { return true; } - //for now, supported attributes are entryUUID, nsuniqueid, objectGUID - $testAttributes = array('entryuuid', 'nsuniqueid', 'objectguid', 'guid'); + //for now, supported attributes are entryUUID, nsuniqueid, objectGUID, ipaUniqueID + $testAttributes = array('entryuuid', 'nsuniqueid', 'objectguid', 'guid', 'ipauniqueid'); foreach($testAttributes as $attribute) { $value = $this->readAttribute($dn, $attribute); @@ -1184,7 +1226,7 @@ class Access extends LDAPUtility { } $offset -= $limit; //we work with cache here - $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . $limit . '-' . $offset; + $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' . intval($limit) . '-' . intval($offset); $cookie = ''; if(isset($this->cookies[$cachekey])) { $cookie = $this->cookies[$cachekey]; @@ -1206,7 +1248,7 @@ class Access extends LDAPUtility { */ private function setPagedResultCookie($base, $filter, $limit, $offset, $cookie) { if(!empty($cookie)) { - $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' .$limit . '-' . $offset; + $cachekey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' .intval($limit) . '-' . intval($offset); $this->cookies[$cachekey] = $cookie; } } @@ -1236,9 +1278,9 @@ class Access extends LDAPUtility { if($this->connection->hasPagedResultSupport && !is_null($limit)) { $offset = intval($offset); //can be null \OCP\Util::writeLog('user_ldap', - 'initializing paged search for Filter'.$filter.' base '.print_r($bases, true) + 'initializing paged search for Filter '.$filter.' base '.print_r($bases, true) .' attr '.print_r($attr, true). ' limit ' .$limit.' offset '.$offset, - \OCP\Util::INFO); + \OCP\Util::DEBUG); //get the cookie from the search for the previous search, required by LDAP foreach($bases as $base) { @@ -1260,7 +1302,7 @@ class Access extends LDAPUtility { } if(!is_null($cookie)) { if($offset > 0) { - \OCP\Util::writeLog('user_ldap', 'Cookie '.$cookie, \OCP\Util::INFO); + \OCP\Util::writeLog('user_ldap', 'Cookie '.CRC32($cookie), \OCP\Util::INFO); } $pagedSearchOK = $this->ldap->controlPagedResult( $this->connection->getConnectionResource(), $limit, diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php index 954d0501fa..c9ed1e648a 100644 --- a/apps/user_ldap/lib/configuration.php +++ b/apps/user_ldap/lib/configuration.php @@ -76,6 +76,8 @@ class Configuration { 'ldapExpertUUIDUserAttr' => null, 'ldapExpertUUIDGroupAttr' => null, 'lastJpegPhotoLookup' => null, + 'ldapNestedGroups' => false, + 'ldapPagingSize' => null, ); /** @@ -118,9 +120,9 @@ class Configuration { $cta = $this->getConfigTranslationArray(); foreach($config as $inputkey => $val) { - if(strpos($inputkey, '_') !== false && isset($cta[$inputkey])) { + if(strpos($inputkey, '_') !== false && array_key_exists($inputkey, $cta)) { $key = $cta[$inputkey]; - } elseif(isset($this->config[$inputkey])) { + } elseif(array_key_exists($inputkey, $this->config)) { $key = $inputkey; } else { continue; @@ -342,6 +344,8 @@ class Configuration { 'ldap_expert_uuid_group_attr' => '', 'has_memberof_filter_support' => 0, 'last_jpegPhoto_lookup' => 0, + 'ldap_nested_groups' => 0, + 'ldap_paging_size' => 500, ); } @@ -393,6 +397,8 @@ class Configuration { 'ldap_expert_uuid_group_attr' => 'ldapExpertUUIDGroupAttr', 'has_memberof_filter_support' => 'hasMemberOfFilterSupport', 'last_jpegPhoto_lookup' => 'lastJpegPhotoLookup', + 'ldap_nested_groups' => 'ldapNestedGroups', + 'ldap_paging_size' => 'ldapPagingSize', ); return $array; } diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index b2075748a3..173c4ebcc2 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -78,6 +78,8 @@ class Connection extends LDAPUtility { //a cloned instance inherits the connection resource. It may use it, //but it may not disconnect it $this->dontDestruct = true; + $this->configuration = new Configuration($this->configPrefix, + !is_null($this->configID)); } public function __get($name) { @@ -132,6 +134,9 @@ class Connection extends LDAPUtility { return $this->ldapConnectionRes; } + /** + * @param string|null $key + */ private function getCacheKey($key) { $prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-'; if(is_null($key)) { diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 7de7fe8667..b5955cb2ab 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -120,7 +120,7 @@ class Helper { $saveOtherConfigurations = ''; if(empty($prefix)) { - $saveOtherConfigurations = 'AND `Configkey` NOT LIKE \'s%\''; + $saveOtherConfigurations = 'AND `configkey` NOT LIKE \'s%\''; } $query = \OCP\DB::prepare(' diff --git a/apps/user_ldap/lib/ldap.php b/apps/user_ldap/lib/ldap.php index de9b7481c1..d1ca91045b 100644 --- a/apps/user_ldap/lib/ldap.php +++ b/apps/user_ldap/lib/ldap.php @@ -139,7 +139,9 @@ class LDAP implements ILDAPWrapper { if(function_exists($func)) { $this->preFunctionCall($func, $arguments); $result = call_user_func_array($func, $arguments); - $this->postFunctionCall(); + if ($result === FALSE) { + $this->postFunctionCall(); + } return $result; } } diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php index b27233bcd1..0eb294eb7a 100644 --- a/apps/user_ldap/lib/proxy.php +++ b/apps/user_ldap/lib/proxy.php @@ -80,6 +80,9 @@ abstract class Proxy { return $result; } + /** + * @param string|null $key + */ private function getCacheKey($key) { $prefix = 'LDAP-Proxy-'; if(is_null($key)) { diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php index e79090febc..8406b2d42a 100644 --- a/apps/user_ldap/lib/wizard.php +++ b/apps/user_ldap/lib/wizard.php @@ -485,7 +485,7 @@ class Wizard extends LDAPUtility { /** * @brief sets the found value for the configuration key in the WizardResult * as well as in the Configuration instance - * @param $key the configuration key + * @param string $key the configuration key * @param $value the (detected) value * @return null * @@ -799,6 +799,7 @@ class Wizard extends LDAPUtility { \OCP\Util::writeLog('user_ldap', 'Wiz: Setting LDAP Options ', \OCP\Util::DEBUG); //set LDAP options $this->ldap->setOption($cr, LDAP_OPT_PROTOCOL_VERSION, 3); + $this->ldap->setOption($cr, LDAP_OPT_REFERRALS, 0); $this->ldap->setOption($cr, LDAP_OPT_NETWORK_TIMEOUT, self::LDAP_NW_TIMEOUT); if($tls) { $isTlsWorking = @$this->ldap->startTls($cr); @@ -869,12 +870,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 +887,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 +910,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 +926,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 +961,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); @@ -980,7 +1001,7 @@ class Wizard extends LDAPUtility { /** * @brief appends a list of values fr * @param $result resource, the return value from ldap_get_attributes - * @param $attribute string, the attribute values to look for + * @param string $attribute the attribute values to look for * @param &$known array, new values will be appended here * @return int, state on of the class constants LRESULT_PROCESSED_OK, * LRESULT_PROCESSED_INVALID or LRESULT_PROCESSED_SKIP diff --git a/apps/user_ldap/lib/wizardresult.php b/apps/user_ldap/lib/wizardresult.php index 542f106cad..9e0936faa6 100644 --- a/apps/user_ldap/lib/wizardresult.php +++ b/apps/user_ldap/lib/wizardresult.php @@ -36,6 +36,10 @@ class WizardResult { $this->markedChange = true; } + /** + * @param string $key + * @param array|string $values + */ public function addOptions($key, $values) { if(!is_array($values)) { $values = array($values); diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index d077eafdde..6b7d8e6f53 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -25,6 +25,7 @@ OC_Util::checkAdminUser(); +OCP\Util::addScript('user_ldap', 'ldapFilter'); OCP\Util::addScript('user_ldap', 'settings'); OCP\Util::addScript('core', 'jquery.multiselect'); OCP\Util::addStyle('user_ldap', 'settings'); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 3ccc7a860f..03f2b8db09 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -1,5 +1,5 @@
-
+
    $title) { ?>
  • @@ -23,7 +23,7 @@

    -

    >

    +

    >


@@ -36,6 +36,8 @@

+

+

t('Special Attributes'));?>

diff --git a/apps/user_ldap/tests/connection.php b/apps/user_ldap/tests/connection.php new file mode 100644 index 0000000000..f51b0c8301 --- /dev/null +++ b/apps/user_ldap/tests/connection.php @@ -0,0 +1,54 @@ +. +* +*/ + +namespace OCA\user_ldap\tests; + +class Test_Connection extends \PHPUnit_Framework_TestCase { + + public function testOriginalAgentUnchangedOnClone() { + //background: upon login a bind is done with the user credentials + //which is valid for the whole LDAP resource. It needs to be reset + //to the agent's credentials + $lw = $this->getMock('\OCA\user_ldap\lib\ILDAPWrapper'); + + $connection = new \OCA\user_ldap\lib\Connection($lw, '', null); + $agent = array( + 'ldapAgentName' => 'agent', + 'ldapAgentPassword' => '123456', + ); + $connection->setConfiguration($agent); + + $testConnection = clone $connection; + $user = array( + 'ldapAgentName' => 'user', + 'ldapAgentPassword' => 'password', + ); + $testConnection->setConfiguration($user); + + $agentName = $connection->ldapAgentName; + $agentPawd = $connection->ldapAgentPassword; + + $this->assertSame($agentName, $agent['ldapAgentName']); + $this->assertSame($agentPawd, $agent['ldapAgentPassword']); + } + +} \ No newline at end of file diff --git a/apps/user_ldap/tests/group_ldap.php b/apps/user_ldap/tests/group_ldap.php new file mode 100644 index 0000000000..ecbd42319e --- /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 0000000000..2b5cabc705 --- /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_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php index 5ad127197f..2cb3dfb2c6 100644 --- a/apps/user_ldap/user_proxy.php +++ b/apps/user_ldap/user_proxy.php @@ -54,11 +54,15 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface { protected function walkBackends($uid, $method, $parameters) { $cacheKey = $this->getUserCacheKey($uid); foreach($this->backends as $configPrefix => $backend) { -// print("walkBackend '$configPrefix'
"); - if($result = call_user_func_array(array($backend, $method), $parameters)) { + $instance = $backend; + if(!method_exists($instance, $method) + && method_exists($this->getAccess($configPrefix), $method)) { + $instance = $this->getAccess($configPrefix); + } + if($result = call_user_func_array(array($instance, $method), $parameters)) { $this->writeToCache($cacheKey, $configPrefix); return $result; - } + } } return false; } @@ -77,7 +81,12 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface { //in case the uid has been found in the past, try this stored connection first if(!is_null($prefix)) { if(isset($this->backends[$prefix])) { - $result = call_user_func_array(array($this->backends[$prefix], $method), $parameters); + $instance = $this->backends[$prefix]; + if(!method_exists($instance, $method) + && method_exists($this->getAccess($prefix), $method)) { + $instance = $this->getAccess($prefix); + } + $result = call_user_func_array(array($instance, $method), $parameters); if($result === $passOnWhen) { //not found here, reset cache to null if user vanished //because sometimes methods return false with a reason diff --git a/apps/user_webdavauth/appinfo/info.xml b/apps/user_webdavauth/appinfo/info.xml index 76b314e48a..20c5909cc1 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 0000000000..118fa2ce30 --- /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/l10n/id.php b/apps/user_webdavauth/l10n/id.php index 278055ce8c..50084bf7f2 100644 --- a/apps/user_webdavauth/l10n/id.php +++ b/apps/user_webdavauth/l10n/id.php @@ -1,5 +1,7 @@ "Otentikasi WebDAV" +"WebDAV Authentication" => "Otentikasi WebDAV", +"Address: " => "Alamat:", +"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." => "Kredensial pengguna akan dikirim ke alamat ini. Pengaya ini memeriksa respon dan akan menafsirkan kode status HTTP 401 dan 403 sebagai kredensial yang tidak valid, dan semua tanggapan lain akan dianggap sebagai kredensial yang valid." ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_webdavauth/l10n/ja.php b/apps/user_webdavauth/l10n/ja.php new file mode 100644 index 0000000000..bab7be008e --- /dev/null +++ b/apps/user_webdavauth/l10n/ja.php @@ -0,0 +1,7 @@ + "WebDAV 認証", +"Address: " => "アドレス:", +"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." => "ユーザーの権限情報をこのアドレスに送信します。このプラグインは応答をチェックし、HTTP状態コードが 401 と 403 の場合は無効な資格情報とし、他の応答はすべて有効な資格情報として処理します。" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_webdavauth/l10n/km.php b/apps/user_webdavauth/l10n/km.php new file mode 100644 index 0000000000..74e61861a9 --- /dev/null +++ b/apps/user_webdavauth/l10n/km.php @@ -0,0 +1,7 @@ + "ការ​ផ្ទៀង​ផ្ទាត់​ភាព​ត្រឹម​ត្រូវ WebDAV", +"Address: " => "អាសយដ្ឋាន៖", +"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." => "អត្តសញ្ញាណ​អ្នក​ប្រើ​នឹង​ត្រូវ​ផ្ញើ​ទៅ​អាសយដ្ឋាន​នេះ។ កម្មវិធី​បន្ថែម​នេះ​ពិនិត្យ​ចម្លើយ​តប ហើយ​នឹង​បក​ស្រាយ​កូដ​ស្ថានភាព HTTP ដូច​ជា 401 និង 403 ថា​ជា​អត្តសញ្ញាណ​មិន​ត្រឹម​ត្រូវ ហើយ​និង​ចម្លើយ​តប​ផ្សេងៗ​ថា​ត្រឹម​ត្រូវ។" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_webdavauth/l10n/nb_NO.php b/apps/user_webdavauth/l10n/nb_NO.php index e7ee8ae56b..c472270388 100644 --- a/apps/user_webdavauth/l10n/nb_NO.php +++ b/apps/user_webdavauth/l10n/nb_NO.php @@ -1,5 +1,7 @@ "Adresse:" +"WebDAV Authentication" => "WebDAV-autentisering", +"Address: " => "Adresse:", +"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." => "Brukerens påloggingsinformasjon vil bli sendt til denne adressen. Denne utvidelsen sjekker svaret og vil tolke HTTP-statuskodene 401 og 403 som ugyldig bruker eller passord, og alle andre svar tolkes som gyldig påloggings." ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/user_webdavauth/l10n/ro.php b/apps/user_webdavauth/l10n/ro.php index 5780805a88..24e3c9f917 100644 --- a/apps/user_webdavauth/l10n/ro.php +++ b/apps/user_webdavauth/l10n/ro.php @@ -1,5 +1,6 @@ "Autentificare WebDAV" +"WebDAV Authentication" => "Autentificare WebDAV", +"Address: " => "Adresa :" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"; diff --git a/apps/user_webdavauth/l10n/vi.php b/apps/user_webdavauth/l10n/vi.php index 1ab4687922..0ba38cc26f 100644 --- a/apps/user_webdavauth/l10n/vi.php +++ b/apps/user_webdavauth/l10n/vi.php @@ -1,5 +1,7 @@ "Xác thực WebDAV" +"WebDAV Authentication" => "Xác thực WebDAV", +"Address: " => "Địa chỉ :", +"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." => "Các thông tin người dùng sẽ được gửi đến địa chỉ này. Plugin này sẽ kiểm tra các phản hồi và các statuscodes HTTP 401 và 403 không hợp lệ, và tất cả những phản h khác như thông tin hợp lệ." ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/user_webdavauth/templates/settings.php b/apps/user_webdavauth/templates/settings.php index ad1701add8..4596fdf3c7 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 b88e9cf68b..4030fc0250 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 c9ed7b96c6..0c395839cf 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/.htaccess b/config/.htaccess new file mode 100644 index 0000000000..2421e9a163 --- /dev/null +++ b/config/.htaccess @@ -0,0 +1,12 @@ +# line below if for Apache 2.4 + +Require all denied + + +# line below if for Apache 2.2 + +deny from all + + +# section for Apache 2.2 and 2.4 +IndexIgnore * diff --git a/config/config.sample.php b/config/config.sample.php index 356843200b..708e836702 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]$" */ @@ -53,6 +53,9 @@ $CONFIG = array( /* The optional authentication for the proxy to use to connect to the internet. The format is: [username]:[password] */ "proxyuserpwd" => "", +/* List of trusted domains, to prevent host header poisoning ownCloud is only using these Host headers */ +'trusted_domains' => array('demo.owncloud.org', 'otherdomain.owncloud.org:8080'), + /* Theme to use for ownCloud */ "theme" => "", @@ -139,7 +142,7 @@ $CONFIG = array( 'allow_user_to_change_display_name' => true, /* Check 3rdparty apps for malicious code fragments */ -"appcodechecker" => "", +"appcodechecker" => true, /* Check if ownCloud is up to date */ "updatechecker" => true, @@ -175,6 +178,9 @@ $CONFIG = array( /* Enable or disable the logging of IP addresses in case of webform auth failures */ "log_authfailip" => false, +/* Whether ownCloud should log the last successfull cron exec */ +"cron_log" => true, + /* * Configure the size in bytes log rotation should happen, 0 or false disables the rotation. * This rotates the current owncloud logfile to a new name, this way the total log usage @@ -267,6 +273,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 25b8b31253..dd2c1026e4 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/preview.php b/core/ajax/preview.php index a1267d6f5c..d38043707a 100644 --- a/core/ajax/preview.php +++ b/core/ajax/preview.php @@ -7,34 +7,45 @@ */ \OC_Util::checkLoggedIn(); -$file = array_key_exists('file', $_GET) ? (string) $_GET['file'] : ''; -$maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '36'; -$maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '36'; -$scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true; +$file = array_key_exists('file', $_GET) ? (string)$_GET['file'] : ''; +$maxX = array_key_exists('x', $_GET) ? (int)$_GET['x'] : '36'; +$maxY = array_key_exists('y', $_GET) ? (int)$_GET['y'] : '36'; +$scalingUp = array_key_exists('scalingup', $_GET) ? (bool)$_GET['scalingup'] : true; +$keepAspect = array_key_exists('a', $_GET) ? true : false; +$always = array_key_exists('forceIcon', $_GET) ? (bool)$_GET['forceIcon'] : true; -if($file === '') { +if ($file === '') { //400 Bad Request \OC_Response::setStatus(400); \OC_Log::write('core-preview', 'No file parameter was passed', \OC_Log::DEBUG); exit; } -if($maxX === 0 || $maxY === 0) { +if ($keepAspect === true) { + $maxY = $maxX; +} + +if ($maxX === 0 || $maxY === 0) { //400 Bad Request \OC_Response::setStatus(400); \OC_Log::write('core-preview', 'x and/or y set to 0', \OC_Log::DEBUG); exit; } -try{ +try { $preview = new \OC\Preview(\OC_User::getUser(), 'files'); - $preview->setFile($file); - $preview->setMaxX($maxX); - $preview->setMaxY($maxY); - $preview->setScalingUp($scalingUp); + if (!$always and !$preview->isMimeSupported(\OC\Files\Filesystem::getMimeType($file))) { + \OC_Response::setStatus(404); + } else { + $preview->setFile($file); + $preview->setMaxX($maxX); + $preview->setMaxY($maxY); + $preview->setScalingUp($scalingUp); + $preview->setKeepAspect($keepAspect); + } - $preview->show(); -}catch(\Exception $e) { + $preview->showPreview(); +} catch (\Exception $e) { \OC_Response::setStatus(500); \OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG); -} \ No newline at end of file +} diff --git a/core/ajax/share.php b/core/ajax/share.php index 86ee018e38..2b41bd8a5d 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(); @@ -80,6 +79,14 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo break; case 'setExpirationDate': if (isset($_POST['date'])) { + $l = OC_L10N::get('core'); + $date = new \DateTime($_POST['date']); + $today = new \DateTime('now'); + + if ($date < $today) { + OC_JSON::error(array('data' => array('message' => $l->t('Expiration date is in the past.')))); + return; + } $return = OCP\Share::setExpirationDate($_POST['itemType'], $_POST['itemSource'], $_POST['date']); ($return) ? OC_JSON::success() : OC_JSON::error(); } @@ -145,10 +152,17 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo } $result = $mailNotification->sendLinkShareMail($to_address, $file, $link, $expiration); - if($result === true) { + if(empty($result)) { \OCP\JSON::success(); } else { - \OCP\JSON::error(array('data' => array('message' => OC_Util::sanitizeHTML($result)))); + $l = OC_L10N::get('core'); + OCP\JSON::error(array( + 'data' => array( + 'message' => $l->t("Couldn't send mail to following users: %s ", + implode(', ', $result) + ) + ) + )); } break; @@ -191,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 d6af84e95b..55e8ab15ec 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -1,6 +1,5 @@ listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) { $eventSource->send('success', (string)$l->t('Updated database')); }); - $updater->listen('\OC\Updater', 'filecacheStart', function () use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('Updating filecache, this may take really long...')); - }); - $updater->listen('\OC\Updater', 'filecacheDone', function () use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('Updated filecache')); - }); - $updater->listen('\OC\Updater', 'filecacheProgress', function ($out) use ($eventSource, $l) { - $eventSource->send('success', (string)$l->t('... %d%% done ...', array('percent' => $out))); - }); $updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource) { $eventSource->send('failure', $message); $eventSource->close(); diff --git a/core/command/upgrade.php b/core/command/upgrade.php index 128d27aa3d..ed72d136e2 100644 --- a/core/command/upgrade.php +++ b/core/command/upgrade.php @@ -27,10 +27,13 @@ class Upgrade extends Command { ; } + /** + * Execute the upgrade command + * + * @param InputInterface $input input interface + * @param OutputInterface $output output interface + */ protected function execute(InputInterface $input, OutputInterface $output) { - global $RUNTIME_NOAPPS; - - $RUNTIME_NOAPPS = true; //no apps, yet require_once \OC::$SERVERROOT . '/lib/base.php'; @@ -53,15 +56,6 @@ class Upgrade extends Command { $updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) { $output->writeln('Updated database'); }); - $updater->listen('\OC\Updater', 'filecacheStart', function () use($output) { - $output->writeln('Updating filecache, this may take really long...'); - }); - $updater->listen('\OC\Updater', 'filecacheDone', function () use($output) { - $output->writeln('Updated filecache'); - }); - $updater->listen('\OC\Updater', 'filecacheProgress', function ($out) use($output) { - $output->writeln('... ' . $out . '% done ...'); - }); $updater->listen('\OC\Updater', 'failure', function ($message) use($output) { $output->writeln($message); @@ -69,6 +63,9 @@ class Upgrade extends Command { }); $updater->upgrade(); + + $this->postUpgradeCheck($input, $output); + return self::ERROR_SUCCESS; } else if(\OC_Config::getValue('maintenance', false)) { //Possible scenario: ownCloud core is updated but an app failed @@ -84,4 +81,21 @@ class Upgrade extends Command { return self::ERROR_UP_TO_DATE; } } + + /** + * Perform a post upgrade check (specific to the command line tool) + * + * @param InputInterface $input input interface + * @param OutputInterface $output output interface + */ + protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) { + $trustedDomains = \OC_Config::getValue('trusted_domains', array()); + if (empty($trustedDomains)) { + $output->write( + 'The setting "trusted_domains" could not be ' . + 'set automatically by the upgrade script, ' . + 'please set it manually' + ); + } + } } diff --git a/core/command/user/report.php b/core/command/user/report.php index 70c5a8566b..a5159310af 100644 --- a/core/command/user/report.php +++ b/core/command/user/report.php @@ -46,7 +46,6 @@ class Report extends Command { } private function countUsers() { - \OC_App::loadApps(array('authentication')); $userManager = \OC::$server->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 f68f53d699..a0bb262854 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; } @@ -187,6 +188,9 @@ } #app-settings.open #app-settings-content { display: block; + /* restrict height of settings and make scrollable */ + max-height: 300px; + overflow-y: auto; } .settings-button { @@ -239,3 +243,34 @@ 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; +} +.appear { + opacity: 1; + transition: opacity 500ms ease 0s; + -moz-transition: opacity 500ms ease 0s; + -ms-transition: opacity 500ms ease 0s; + -o-transition: opacity 500ms ease 0s; + -webkit-transition: opacity 500ms ease 0s; +} +.appear.transparent { + opacity: 0; +} diff --git a/core/css/auth.css b/core/css/auth.css deleted file mode 100644 index 70df9f0ae0..0000000000 --- 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/icons.css b/core/css/icons.css index 814749c5af..cdfdd8e43e 100644 --- a/core/css/icons.css +++ b/core/css/icons.css @@ -1,4 +1,4 @@ -.icon { +[class^="icon-"], [class*=" icon-"] { background-repeat: no-repeat; background-position: center; } @@ -24,7 +24,7 @@ .icon-noise { background-image: url('../img/noise.png'); - background-repeat: no-repeat; + background-repeat: repeat; } @@ -66,7 +66,8 @@ .icon-delete { background-image: url('../img/actions/delete.svg'); } -.icon-delete-hover { +.icon-delete:hover, +.icon-delete:focus { background-image: url('../img/actions/delete-hover.svg'); } @@ -155,11 +156,15 @@ background-image: url('../img/actions/sound-off.svg'); } -.icon-star { +.icon-star, +.icon-starred:hover, +.icon-starred:focus { background-image: url('../img/actions/star.svg'); } -.icon-starred { +.icon-starred, +.icon-star:hover, +.icon-star:focus { background-image: url('../img/actions/starred.svg'); } diff --git a/core/css/jquery.ocdialog.css b/core/css/jquery.ocdialog.css index 236968e324..a1221137bc 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 a63aa902d3..fd0628d7e2 100644 --- a/core/css/mobile.css +++ b/core/css/mobile.css @@ -1,4 +1,17 @@ -@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; +} +/* do not show menu toggle on public share links as there is no menu */ +#body-public #owncloud.menutoggle { + background-image: none; + padding-right: 0 !important; +} /* compress search box on mobile, expand when focused */ .searchbox input[type="search"] { @@ -11,6 +24,7 @@ .searchbox input[type="search"]:focus, .searchbox input[type="search"]:active { width: 155px; + max-width: 50%; } /* do not show display name on mobile when profile picture is present */ @@ -18,5 +32,88 @@ 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; +} + + +/* fix error display on smaller screens */ +.error-wide { + width: 100%; + margin-left: 0 !important; + -moz-box-sizing: border-box; + box-sizing: border-box; +} } diff --git a/core/css/styles.css b/core/css/styles.css index 341a507ce3..26aaa1be94 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -10,15 +10,32 @@ table { border-collapse:separate; border-spacing:0; white-space:nowrap; } caption, th, td { text-align:left; font-weight:normal; } table, td, th { vertical-align:middle; } a { border:0; color:#000; text-decoration:none;} -a, a *, input, input *, select, .button span, li, label { cursor:pointer; } +a, a *, input, input *, select, .button span, label { cursor:pointer; } ul { list-style:none; } -body { background:#fefefe; font:normal .8em/1.6em "Helvetica Neue",Helvetica,Arial,FreeSans,sans-serif; color:#000; } + + +body { + background: #fefefe; + font: normal .8em/1.6em "Helvetica Neue",Helvetica,Arial,FreeSans,sans-serif; + color: #000; + height: auto; +} /* HEADERS */ -#body-user #header, #body-settings #header { - position:fixed; top:0; left:0; right:0; z-index:100; height:45px; line-height:2.5em; - background:#1d2d44 url('../img/noise.png') repeat; +#body-user #header, +#body-settings #header, +#body-public #header { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 100; + height: 45px; + line-height: 2.5em; + background: #1d2d44 url('../img/noise.png') repeat; + -moz-box-sizing: border-box; + box-sizing: border-box; } #body-login { @@ -33,9 +50,24 @@ body { background:#fefefe; font:normal .8em/1.6em "Helvetica Neue",Helvetica,Ari filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#35537a', endColorstr='#1d2d44',GradientType=0 ); /* IE6-9 */ } -#owncloud { position:absolute; top:0; left:0; padding:6px; padding-bottom:0; } -.header-right { float:right; vertical-align:middle; padding:0.5em; } -.header-right > * { vertical-align:middle; } +#owncloud { + position: absolute; + top: 0; + left: 0; + padding: 6px; + padding-bottom: 0; +} + +/* info part on the right, used e.g. for info on who shared something */ +.header-right { + position: absolute; + right: 0; + padding: 7px 5px; + color: #fff; + height: 100%; + max-width: 40%; + white-space: nowrap; +} /* Profile picture in header */ #header .avatardiv { @@ -77,6 +109,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 +117,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 +133,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"] { @@ -151,6 +192,12 @@ input[type="time"] { height: 31px; -moz-box-sizing: border-box; box-sizing: border-box; } + +/* correctly align images inside of buttons */ +input img, button img, .button img { + vertical-align: text-bottom; +} + #quota { cursor: default; margin: 30px; @@ -168,13 +215,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; } input[type="submit"]:hover, input[type="submit"]:focus, input[type="button"]:hover, input[type="button"]:focus, @@ -204,18 +250,18 @@ textarea:disabled { /* Primary action button, use sparingly */ .primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary { border: 1px solid #1d2d44; - background: #35537a; + background-color: #35537a; color: #ddd; } .primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover, .primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus { border: 1px solid #1d2d44; - background: #304d76; + background-color: #304d76; color: #fff; } .primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active { border: 1px solid #1d2d44; - background: #1d2d44; + background-color: #1d2d44; color: #bbb; } @@ -233,7 +279,7 @@ textarea:disabled { } input[type="submit"].enabled { - background: #66f866; + background-color: #66f866; border: 1px solid #5e5; } @@ -245,6 +291,7 @@ input[type="submit"].enabled { -webkit-box-sizing: border-box; box-sizing: border-box; position: fixed; + top:45px; right: 0; left: 0; height: 44px; @@ -274,6 +321,10 @@ input[type="submit"].enabled { padding: 7px 10px } +#controls .button.hidden { + display: none; +} + #content { position:relative; height:100%; width:100%; } #content .hascontrols { position: relative; @@ -283,21 +334,6 @@ input[type="submit"].enabled { position:absolute; height:100%; width:100%; padding-left:80px; padding-top: 45px; -moz-box-sizing:border-box; box-sizing:border-box; } -#leftcontent, .leftcontent { - position:relative; overflow:auto; width:256px; height:100%; - background:#f8f8f8; border-right:1px solid #ddd; - -moz-box-sizing:border-box; box-sizing:border-box; -} -#leftcontent li, .leftcontent li { background:#f8f8f8; padding:.5em .8em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; -webkit-transition:background-color 200ms; -moz-transition:background-color 200ms; -o-transition:background-color 200ms; transition:background-color 200ms; } -#leftcontent li:hover, #leftcontent li:active, #leftcontent li.active, .leftcontent li:hover, .leftcontent li:active, .leftcontent li.active { background:#eee; } -#leftcontent li.active, .leftcontent li.active { font-weight:bold; } -#leftcontent li:hover, .leftcontent li:hover { color:#333; background:#ddd; } -#leftcontent a { height:100%; display:block; margin:0; padding:0 1em 0 0; float:left; } -#rightcontent, .rightcontent { position:fixed; top:89px; left: 336px; overflow:auto } - -#controls + .leftcontent{ - top: 44px; -} #emptycontent { font-size: 1.5em; @@ -393,23 +429,36 @@ input[type="submit"].enabled { } /* Icons for username and password fields to better recognize them */ -#adminlogin, #adminpass, #user, #password { width:11.7em!important; padding-left:1.8em; } -#adminlogin+label+img, #adminpass-icon, #user+label+img, #password-icon { - position:absolute; left:1.25em; top:1.65em; - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; filter:alpha(opacity=30); opacity:.3; +#adminlogin, +#adminpass, +input[name='adminpass-clone'], +#user, +#password, +input[name='password-clone'] { + width: 223px !important; + padding-left: 36px !important; +} +#adminlogin+label+img, +#adminpass-icon, +#user+label+img, +#password-icon { + position: absolute; + left: 1.25em; + top: 1.65em; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; + filter: alpha(opacity=30); + opacity: .3; +} +#adminpass-icon, #password-icon { + top: 1.1em; } -#adminpass-icon, #password-icon { top:1.1em; } -input[name="password-clone"] { padding-left:1.8em; width:11.7em !important; } -input[name="adminpass-clone"] { padding-left:1.8em; width:11.7em !important; } /* General new input field look */ #body-login input[type="text"], #body-login input[type="password"], -#body-login input[type="email"] { - border: 1px solid #323233; - border-radius: 5px; -} -#body-login input[type='submit'] { +#body-login input[type="email"], +#body-login input[type="submit"] { + border: none; border-radius: 5px; } @@ -441,15 +490,22 @@ input[name="adminpass-clone"] { padding-left:1.8em; width:11.7em !important; } p.infield { position:relative; } label.infield { cursor:text !important; top:1.05em; left:.85em; } #body-login form label.infield { /* labels are ellipsized when too long, keep them short */ - position:absolute; width:90%; padding-left:1.4em; - font-size:19px; color:#aaa; - white-space:nowrap; overflow:hidden; text-overflow:ellipsis; + position: absolute; + width: 82%; + margin-left: 26px; + font-size: 19px; + color: #aaa; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +#body-login #databaseField .infield { + margin-left: 0; } -#body-login #databaseField .infield { padding-left:0; } #body-login form input[type="checkbox"]+label { position: relative; margin: 0; - font-size: 1em; + font-size: 13px; padding: 14px; padding-left: 28px; margin-left: -28px; @@ -463,8 +519,6 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } } #body-login #showAdvanced > img { - height: 16px; - width: 16px; padding: 4px; box-sizing: border-box; } @@ -575,8 +629,8 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } } .error-wide { - width: 800px; - margin-left: -250px; + width: 700px; + margin-left: -200px !important; } /* Fixes for log in page, TODO should be removed some time */ @@ -603,11 +657,13 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } /* Log in and install button */ #body-login input { - font-size: 1.5em; + font-size: 20px; + margin: 5px; + padding: 12px 10px 8px; } #body-login input[type="text"], #body-login input[type="password"] { - width: 13em; + width: 249px; } #body-login input.login { width: auto; @@ -617,7 +673,7 @@ label.infield { cursor:text !important; top:1.05em; left:.85em; } padding: 10px 20px; /* larger log in and installation buttons */ } #remember_login { - margin: 18px 5px 0 18px; + margin: 24px 5px 0 16px !important; vertical-align: text-bottom; } @@ -791,20 +847,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); @@ -923,6 +971,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/img/actions/add.png b/core/img/actions/add.png index 3c051e4d73..8ae17cfe11 100644 Binary files a/core/img/actions/add.png and b/core/img/actions/add.png differ diff --git a/core/img/actions/add.svg b/core/img/actions/add.svg index 250746e166..ecbab6f13a 100644 --- a/core/img/actions/add.svg +++ b/core/img/actions/add.svg @@ -1,6 +1,5 @@ - - - + + diff --git a/core/img/actions/close.png b/core/img/actions/close.png index 3389c66e03..ece33258e5 100644 Binary files a/core/img/actions/close.png and b/core/img/actions/close.png differ diff --git a/core/img/actions/close.svg b/core/img/actions/close.svg index ef564bfd48..4471dbc630 100644 --- a/core/img/actions/close.svg +++ b/core/img/actions/close.svg @@ -1,6 +1,3 @@ - - - - + diff --git a/core/img/actions/delete-hover.png b/core/img/actions/delete-hover.png index 48e6c089c9..3f8cb6eff9 100644 Binary files a/core/img/actions/delete-hover.png and b/core/img/actions/delete-hover.png differ diff --git a/core/img/actions/delete-hover.svg b/core/img/actions/delete-hover.svg index 9e5150359d..9583ec15b3 100644 --- a/core/img/actions/delete-hover.svg +++ b/core/img/actions/delete-hover.svg @@ -1,4 +1,4 @@ - + diff --git a/core/img/actions/delete.png b/core/img/actions/delete.png index 3389c66e03..e891b370cc 100644 Binary files a/core/img/actions/delete.png and b/core/img/actions/delete.png differ diff --git a/core/img/actions/delete.svg b/core/img/actions/delete.svg index ef564bfd48..f0a3cd4db8 100644 --- a/core/img/actions/delete.svg +++ b/core/img/actions/delete.svg @@ -1,6 +1,4 @@ - - - + diff --git a/core/img/actions/download.png b/core/img/actions/download.png index 0f71a5a776..1f8e1a4f7e 100644 Binary files a/core/img/actions/download.png and b/core/img/actions/download.png differ diff --git a/core/img/actions/download.svg b/core/img/actions/download.svg index a469c3b8a0..0d698bca8d 100644 --- a/core/img/actions/download.svg +++ b/core/img/actions/download.svg @@ -1,6 +1,5 @@ - - + diff --git a/core/img/actions/upload.png b/core/img/actions/upload.png index f6a0c4cfa8..a6969c23fa 100644 Binary files a/core/img/actions/upload.png and b/core/img/actions/upload.png differ diff --git a/core/img/actions/upload.svg b/core/img/actions/upload.svg index eae4515c72..80231797c9 100644 --- a/core/img/actions/upload.svg +++ b/core/img/actions/upload.svg @@ -1,6 +1,4 @@ - - - - + + diff --git a/core/img/actions/view-close.png b/core/img/actions/view-close.png index 8422b73346..c21f6ee30e 100644 Binary files a/core/img/actions/view-close.png and b/core/img/actions/view-close.png differ diff --git a/core/img/actions/view-close.svg b/core/img/actions/view-close.svg index 1d5b1a9f49..89d1fab88d 100644 --- a/core/img/actions/view-close.svg +++ b/core/img/actions/view-close.svg @@ -1,6 +1,3 @@ - - - - + diff --git a/core/img/logo-mail.gif b/core/img/logo-mail.gif index 6a1caaa918..f1dd108450 100644 Binary files a/core/img/logo-mail.gif and b/core/img/logo-mail.gif differ diff --git a/core/js/compatibility.js b/core/js/compatibility.js index 6548f95d42..c07288857f 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/config.php b/core/js/config.php index 139c3b6d48..7e23f3e2e4 100644 --- a/core/js/config.php +++ b/core/js/config.php @@ -10,12 +10,15 @@ header("Content-type: text/javascript"); // Disallow caching -header("Cache-Control: no-cache, must-revalidate"); -header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); +header("Cache-Control: no-cache, must-revalidate"); +header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Enable l10n support $l = OC_L10N::get('core'); +// Enable OC_Defaults support +$defaults = new OC_Defaults(); + // Get the config $apps_paths = array(); foreach(OC_App::getEnabledApps() as $app) { @@ -58,11 +61,30 @@ $array = array( "firstDay" => json_encode($l->l('firstday', 'firstday')) , "oc_config" => json_encode( array( - 'session_lifetime' => \OCP\Config::getSystemValue('session_lifetime', ini_get('session.gc_maxlifetime')), - 'session_keepalive' => \OCP\Config::getSystemValue('session_keepalive', true) + 'session_lifetime' => \OCP\Config::getSystemValue('session_lifetime', ini_get('session.gc_maxlifetime')), + 'session_keepalive' => \OCP\Config::getSystemValue('session_keepalive', true), + 'version' => implode('.', OC_Util::getVersion()), + 'versionstring' => OC_Util::getVersionString(), + ) + ), + "oc_defaults" => json_encode( + array( + 'entity' => $defaults->getEntity(), + 'name' => $defaults->getName(), + 'title' => $defaults->getTitle(), + 'baseUrl' => $defaults->getBaseUrl(), + 'syncClientUrl' => $defaults->getSyncClientUrl(), + 'docBaseUrl' => $defaults->getDocBaseUrl(), + 'slogan' => $defaults->getSlogan(), + 'logoClaim' => $defaults->getLogoClaim(), + 'shortFooter' => $defaults->getShortFooter(), + 'longFooter' => $defaults->getLongFooter() ) ) - ); +); + +// Allow hooks to modify the output values +OC_Hook::emit('\OCP\Config', 'js', array('array' => &$array)); // Echo it foreach ($array as $setting => $value) { diff --git a/core/js/core.json b/core/js/core.json index 4beab7cf79..05c2a17a67 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", @@ -17,7 +18,6 @@ "eventsource.js", "config.js", "multiselect.js", - "router.js", "oc-requesttoken.js" ] } diff --git a/core/js/eventsource.js b/core/js/eventsource.js index 536b180bc8..70f4a2a9aa 100644 --- a/core/js/eventsource.js +++ b/core/js/eventsource.js @@ -20,16 +20,16 @@ */ /** - * wrapper for server side events (http://en.wikipedia.org/wiki/Server-sent_events) + * Wrapper for server side events (http://en.wikipedia.org/wiki/Server-sent_events) * includes a fallback for older browsers and IE * - * use server side events with causion, to many open requests can hang the server + * Use server side events with caution, too many open requests can hang the server */ /** - * create a new event source - * @param string src - * @param object data to be send as GET + * Create a new event source + * @param {string} src + * @param {object} [data] to be send as GET */ OC.EventSource=function(src,data){ var dataStr=''; @@ -74,12 +74,12 @@ OC.EventSource=function(src,data){ this.close(); } }.bind(this)); -} +}; OC.EventSource.fallBackSources=[]; OC.EventSource.iframeCount=0;//number of fallback iframes OC.EventSource.fallBackCallBack=function(id,type,data){ OC.EventSource.fallBackSources[id].fallBackCallBack(type,data); -} +}; OC.EventSource.prototype={ typelessListeners:[], iframe:null, @@ -127,4 +127,4 @@ OC.EventSource.prototype={ this.source.close(); } } -} +}; diff --git a/core/js/jquery-1.10.0.js b/core/js/jquery-1.10.0.js new file mode 100644 index 0000000000..f38148cf12 --- /dev/null +++ b/core/js/jquery-1.10.0.js @@ -0,0 +1,9800 @@ +/*! + * jQuery JavaScript Library v1.10.0 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-05-24T18:39Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.0", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.9.4-pre + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-05-15 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function() { return 0; }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * For feature detection + * @param {Function} fn The function to test for native support + */ +function isNative( fn ) { + return rnative.test( fn + "" ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied if the test fails + * @param {Boolean} test The result of a test. If true, null will be set as the handler in leiu of the specified handler + */ +function addHandle( attrs, handler, test ) { + attrs = attrs.split("|"); + var current, + i = attrs.length, + setHandle = test ? null : handler; + + while ( i-- ) { + // Don't override a user's handler + if ( !(current = Expr.attrHandle[ attrs[i] ]) || current === handler ) { + Expr.attrHandle[ attrs[i] ] = setHandle; + } + } +} + +/** + * Fetches boolean attributes by node + * @param {Element} elem + * @param {String} name + */ +function boolHandler( elem, name ) { + // XML does not need to be checked as this will not be assigned for XML documents + var val = elem.getAttributeNode( name ); + return val && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; +} + +/** + * Fetches attributes without interpolation + * http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx + * @param {Element} elem + * @param {String} name + */ +function interpolationHandler( elem, name ) { + // XML does not need to be checked as this will not be assigned for XML documents + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); +} + +/** + * Uses defaultValue to retrieve value in IE6/7 + * @param {Element} elem + * @param {String} name + */ +function valueHandler( elem ) { + // Ignore the value *property* on inputs by using defaultValue + // Fallback to Sizzle.attr by returning undefined where appropriate + // XML does not need to be checked as this will not be assigned for XML documents + if ( elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns Returns -1 if a precedes b, 1 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + + // Support: IE<8 + // Prevent attribute/property "interpolation" + div.innerHTML = ""; + addHandle( "type|href|height|width", interpolationHandler, div.firstChild.getAttribute("href") === "#" ); + + // Support: IE<9 + // Use getAttributeNode to fetch booleans when getAttribute lies + addHandle( booleans, boolHandler, div.getAttribute("disabled") == null ); + + div.className = "i"; + return !div.getAttribute("className"); + }); + + // Support: IE<9 + // Retrieving value should defer to defaultValue + support.input = assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; + }); + + // IE6/7 still return empty string for value, + // but are actually retrieving the property + addHandle( "value", valueHandler, support.attributes && support.input ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = isNative(doc.querySelectorAll)) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = isNative( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = isNative(docElem.contains) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) + // Detached nodes confoundingly follow *each other* + support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( doc.createElement("div") ) & 1; + }); + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = ( fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined ); + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// Deprecated +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Initialize against the default document +setDocument(); + +// Support: Chrome<<14 +// Always assume duplicates if they aren't passed to the comparison function +[0, 0].sort( sortOrder ); +support.detectDuplicates = hasDuplicate; + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( list && ( !fired || stack ) ) { + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + hooks.cur = fn; + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + var bool = typeof state === "boolean"; + + return this.each(function() { + if ( bool ? state : isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("