diff --git a/.jshintrc b/.jshintrc index 77f9e9f143..d5da3e3082 100644 --- a/.jshintrc +++ b/.jshintrc @@ -26,6 +26,7 @@ "fakeServer": true, "_": true, "OC": true, + "OCA": true, "t": true, "n": true } 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/apps/files/ajax/list.php b/apps/files/ajax/list.php index 2d76b68501..bae3628402 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -17,8 +17,11 @@ $baseUrl = OCP\Util::linkTo('files', 'index.php') . '?dir='; $permissions = $dirInfo->getPermissions(); +$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name'; +$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false; + // make filelist -$files = \OCA\Files\Helper::getFiles($dir); +$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection); $data['directory'] = $dir; $data['files'] = \OCA\Files\Helper::formatFileInfos($files); diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index 15a2913378..4b0db457ad 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -19,3 +19,13 @@ $templateManager->registerTemplate('text/html', 'core/templates/filetemplates/te $templateManager->registerTemplate('application/vnd.oasis.opendocument.presentation', 'core/templates/filetemplates/template.odp'); $templateManager->registerTemplate('application/vnd.oasis.opendocument.text', 'core/templates/filetemplates/template.odt'); $templateManager->registerTemplate('application/vnd.oasis.opendocument.spreadsheet', 'core/templates/filetemplates/template.ods'); + +\OCA\Files\App::getNavigationManager()->add( + array( + "id" => 'files', + "appname" => 'files', + "script" => 'list.php', + "order" => 0, + "name" => $l->t('All files') + ) +); diff --git a/apps/files/appinfo/update.php b/apps/files/appinfo/update.php deleted file mode 100644 index f920f84216..0000000000 --- a/apps/files/appinfo/update.php +++ /dev/null @@ -1,46 +0,0 @@ -getDatabasePlatform()-> - getConcatExpression( '\'{DAV:}\'', '`propertyname`' ); - $query = OC_DB::prepare(' - UPDATE `*PREFIX*properties` - SET `propertyname` = ' . $concat . ' - WHERE `propertyname` NOT LIKE \'{%\' - '); - $query->execute(); -} - -//update from OC 3 - -//try to remove remaining files. -//Give a warning if not possible - -$filesToRemove = array( - 'ajax', - 'appinfo', - 'css', - 'js', - 'l10n', - 'templates', - 'admin.php', - 'download.php', - 'index.php', - 'settings.php' -); - -foreach($filesToRemove as $file) { - $filepath = OC::$SERVERROOT . '/files/' . $file; - if(!file_exists($filepath)) { - continue; - } - $success = OCP\Files::rmdirr($filepath); - if($success === false) { - //probably not sufficient privileges, give up and give a message. - OCP\Util::writeLog('files', 'Could not clean /files/ directory.' - .' Please remove everything except webdav.php from ' . OC::$SERVERROOT . '/files/', OCP\Util::ERROR); - break; - } -} diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 533050691d..009cb355ba 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -3,10 +3,11 @@ See the COPYING-README file. */ /* FILE MENU */ -.actions { padding:5px; height:32px; width: 100%; } +.actions { padding:5px; height:32px; display: inline-block; float: left; } .actions input, .actions button, .actions .button { margin:0; float:left; } .actions .button a { color: #555; } .actions .button a:hover, .actions .button a:active { color: #333; } +.actions.hidden { display: none; } #new { z-index: 1010; @@ -75,6 +76,7 @@ top: 44px; width: 100%; } + /* make sure there's enough room for the file actions */ #body-user #filestable { min-width: 688px; /* 768 (mobile break) - 80 (nav width) */ @@ -83,6 +85,40 @@ min-width: 688px; /* 768 (mobile break) - 80 (nav width) */ } +#filestable tbody tr { background-color:#fff; height:51px; } + +.app-files #app-content { + position: relative; +} + +/** + * Override global #controls styles + * to be more flexible / relative + */ +#body-user .app-files #controls { + left: 310px; /* main nav bar + sidebar */ + position: fixed; + padding-left: 0px; +} + +/* this is mostly for file viewer apps, text editor, etc */ +#body-user .app-files.no-sidebar #controls { + left: 0px; + padding-left: 80px; /* main nav bar */ +} + +.app-files #app-navigation { + width: 230px; +} + +.app-files #app-settings { + width: 229px; /* DUH */ +} + +.app-files #app-settings input { + width: 90%; +} + #filestable tbody tr { background-color:#fff; height:40px; } #filestable tbody tr:hover, tbody tr:active { background-color: rgb(240,240,240); @@ -116,10 +152,29 @@ tr:hover span.extension { table tr.mouseOver td { background-color:#eee; } table th { height:24px; padding:0 8px; color:#999; } -table th .name { - position: absolute; - left: 55px; - top: 15px; +table th .columntitle { + display: inline-block; + padding: 15px; + width: 100%; + height: 50px; + box-sizing: border-box; + -moz-box-sizing: border-box; + vertical-align: middle; +} +table th .columntitle.name { + padding-left: 5px; + margin-left: 50px; + max-width: 300px; +} +/* hover effect on sortable column */ +table th a.columntitle:hover { + background-color: #F0F0F0; +} +table th .sort-indicator { + width: 10px; + height: 8px; + margin-left: 10px; + display: inline-block; } table th, table td { border-bottom:1px solid #ddd; text-align:left; font-weight:normal; } table td { @@ -139,8 +194,11 @@ table th#headerName { } table th#headerSize, table td.filesize { min-width: 48px; - padding: 0 16px; text-align: right; + padding: 0; +} +table table td.filesize { + padding: 0 16px; } table th#headerDate, table td.date { -moz-box-sizing: border-box; @@ -161,9 +219,7 @@ table.multiselect thead { z-index: 10; -moz-box-sizing: border-box; box-sizing: border-box; - left: 0; - padding-left: 80px; - width: 100%; + left: 310px; /* main nav bar + sidebar */ } table.multiselect thead th { @@ -197,10 +253,6 @@ table td.filename input.filename { table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; } table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; } -#modified { - position: absolute; - top: 15px; -} .modified { position: relative; padding-left: 8px; @@ -254,7 +306,7 @@ table td.filename form { font-size:14px; margin-left:48px; margin-right:48px; } /* Use label to have bigger clickable size for checkbox */ #fileList tr td.filename>input[type="checkbox"] + label, -#select_all + label { +.select-all + label { height: 50px; position: absolute; width: 50px; @@ -268,10 +320,10 @@ table td.filename form { font-size:14px; margin-left:48px; margin-right:48px; } #fileList tr td.filename>input[type="checkbox"] + label { left: 0; } -#select_all + label { +.select-all + label { top: 0; } -#select_all { +.select-all { position: absolute; top: 18px; left: 18px; @@ -319,6 +371,9 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; } display: inline; padding: 17px 5px; } +.selectedActions a.hidden { + display: none; +} .selectedActions a img { position:relative; top:5px; @@ -394,7 +449,7 @@ table.dragshadow td.size { } .mask { z-index: 50; - position: fixed; + position: absolute; top: 0; left: 0; right: 0; diff --git a/apps/files/index.php b/apps/files/index.php index a4e9a93850..e24c535cb2 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -28,6 +28,7 @@ OCP\User::checkLoggedIn(); OCP\Util::addStyle('files', 'files'); OCP\Util::addStyle('files', 'upload'); OCP\Util::addStyle('files', 'mobile'); +OCP\Util::addscript('files', 'app'); OCP\Util::addscript('files', 'file-upload'); OCP\Util::addscript('files', 'jquery.iframe-transport'); OCP\Util::addscript('files', 'jquery.fileupload'); @@ -37,28 +38,23 @@ 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, false); -// Redirect if directory does not exist -if (!$dirInfo || !$dirInfo->getType() === 'dir') { - header('Location: ' . OCP\Util::getScriptName() . ''); - exit(); -} $isIE8 = false; preg_match('/MSIE (.*?);/', $_SERVER['HTTP_USER_AGENT'], $matches); -if (count($matches) > 0 && $matches[1] <= 8){ +if (count($matches) > 0 && $matches[1] <= 9) { $isIE8 = true; } -// if IE8 and "?dir=path" was specified, reformat the URL to use a hash like "#?dir=path" -if ($isIE8 && isset($_GET['dir'])){ - if ($dir === ''){ - $dir = '/'; +// if IE8 and "?dir=path&view=someview" was specified, reformat the URL to use a hash like "#?dir=path&view=someview" +if ($isIE8 && (isset($_GET['dir']) || isset($_GET['view']))) { + $hash = '#?'; + $dir = isset($_GET['dir']) ? $_GET['dir'] : '/'; + $view = isset($_GET['view']) ? $_GET['view'] : 'files'; + $hash = '#?dir=' . \OCP\Util::encodePath($dir); + if ($view !== 'files') { + $hash .= '&view=' . urlencode($view); } - header('Location: ' . OCP\Util::linkTo('files', 'index.php') . '#?dir=' . \OCP\Util::encodePath($dir)); + header('Location: ' . OCP\Util::linkTo('files', 'index.php') . $hash); exit(); } @@ -66,49 +62,62 @@ $user = OC_User::getUser(); $config = \OC::$server->getConfig(); -// needed for share init, permissions will be reloaded -// anyway with ajax load -$permissions = $dirInfo->getPermissions(); - -// 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'); +// mostly for the home storage's free space +$dirInfo = \OC\Files\Filesystem::getFileInfo('/', false); +$storageInfo=OC_Helper::getStorageInfo('/', $dirInfo); // 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(); + $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); +$nav = new OCP\Template('files', 'appnavigation', ''); + +$navItems = \OCA\Files\App::getNavigationManager()->getAll(); +$nav->assign('navigationItems', $navItems); + +$contentItems = array(); + +function renderScript($appName, $scriptName) { + $content = ''; + $appPath = OC_App::getAppPath($appName); + $scriptPath = $appPath . '/' . $scriptName; + if (file_exists($scriptPath)) { + // TODO: sanitize path / script name ? + ob_start(); + include $scriptPath; + $content = ob_get_contents(); + @ob_end_clean(); + } + return $content; +} + +// render the container content for every navigation item +foreach ($navItems as $item) { + $content = ''; + if (isset($item['script'])) { + $content = renderScript($item['appname'], $item['script']); + } + $contentItem = array(); + $contentItem['id'] = $item['id']; + $contentItem['content'] = $content; + $contentItems[] = $contentItem; } OCP\Util::addscript('files', 'fileactions'); OCP\Util::addscript('files', 'files'); +OCP\Util::addscript('files', 'navigation'); 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->assign('appNavigation', $nav); +$tmpl->assign('appContents', $contentItems); +$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); $tmpl->printPage(); diff --git a/apps/files/js/app.js b/apps/files/js/app.js new file mode 100644 index 0000000000..9155fb38cd --- /dev/null +++ b/apps/files/js/app.js @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014 + * + * @author Vincent Petry + * @copyright 2014 Vincent Petry + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +/* global dragOptions, folderDropOptions */ +(function() { + + if (!OCA.Files) { + OCA.Files = {}; + } + + var App = { + navigation: null, + + initialize: function() { + this.navigation = new OCA.Files.Navigation($('#app-navigation')); + + // TODO: ideally these should be in a separate class / app (the embedded "all files" app) + this.fileActions = OCA.Files.FileActions; + this.files = OCA.Files.Files; + + this.fileList = new OCA.Files.FileList( + $('#app-content-files'), { + scrollContainer: $('#app-content'), + dragOptions: dragOptions, + folderDropOptions: folderDropOptions + } + ); + this.files.initialize(); + this.fileActions.registerDefaultActions(this.fileList); + this.fileList.setFileActions(this.fileActions); + + // for backward compatibility, the global FileList will + // refer to the one of the "files" view + window.FileList = this.fileList; + + this._setupEvents(); + // trigger URL change event handlers + this._onPopState(OC.Util.History.parseUrlQuery()); + }, + + /** + * Returns the container of the currently visible app. + * + * @return app container + */ + getCurrentAppContainer: function() { + return this.navigation.getActiveContainer(); + }, + + /** + * Setup events based on URL changes + */ + _setupEvents: function() { + OC.Util.History.addOnPopStateHandler(_.bind(this._onPopState, this)); + + // detect when app changed their current directory + $('#app-content').delegate('>div', 'changeDirectory', _.bind(this._onDirectoryChanged, this)); + $('#app-content').delegate('>div', 'changeViewerMode', _.bind(this._onChangeViewerMode, this)); + + $('#app-navigation').on('itemChanged', _.bind(this._onNavigationChanged, this)); + }, + + /** + * Event handler for when the current navigation item has changed + */ + _onNavigationChanged: function(e) { + var params; + if (e && e.itemId) { + params = { + view: e.itemId, + dir: '/' + }; + this._changeUrl(params.view, params.dir); + this.navigation.getActiveContainer().trigger(new $.Event('urlChanged', params)); + } + }, + + /** + * Event handler for when an app notified that its directory changed + */ + _onDirectoryChanged: function(e) { + if (e.dir) { + this._changeUrl(this.navigation.getActiveItem(), e.dir); + } + }, + + /** + * Event handler for when an app notifies that it needs space + * for viewer mode. + */ + _onChangeViewerMode: function(e) { + var state = !!e.viewerModeEnabled; + $('#app-navigation').toggleClass('hidden', state); + $('.app-files').toggleClass('viewer-mode no-sidebar', state); + }, + + /** + * Event handler for when the URL changed + */ + _onPopState: function(params) { + params = _.extend({ + dir: '/', + view: 'files' + }, params); + var lastId = this.navigation.getActiveItem(); + if (!this.navigation.itemExists(params.view)) { + params.view = 'files'; + } + this.navigation.setActiveItem(params.view, {silent: true}); + if (lastId !== this.navigation.getActiveItem()) { + this.navigation.getActiveContainer().trigger(new $.Event('show')); + } + this.navigation.getActiveContainer().trigger(new $.Event('urlChanged', params)); + }, + + /** + * Change the URL to point to the given dir and view + */ + _changeUrl: function(view, dir) { + var params = {dir: dir}; + if (view !== 'files') { + params.view = view; + } + OC.Util.History.pushState(params); + } + }; + OCA.Files.App = App; +})(); + +$(document).ready(function() { + // wait for other apps/extensions to register their event handlers + // in the "ready" clause + _.defer(function() { + OCA.Files.App.initialize(); + }); +}); + diff --git a/apps/files/js/breadcrumb.js b/apps/files/js/breadcrumb.js index 5bc2fac136..c017d710d6 100644 --- a/apps/files/js/breadcrumb.js +++ b/apps/files/js/breadcrumb.js @@ -159,7 +159,11 @@ this.totalWidth = 64; // FIXME: this class should not know about global elements if ( $('#navigation').length ) { - this.totalWidth += $('#navigation').get(0).offsetWidth; + this.totalWidth += $('#navigation').outerWidth(); + } + + if ( $('#app-navigation').length && !$('#app-navigation').hasClass('hidden')) { + this.totalWidth += $('#app-navigation').outerWidth(); } this.hiddenBreadcrumbs = 0; @@ -167,8 +171,8 @@ this.totalWidth += $(this.breadcrumbs[i]).get(0).offsetWidth; } - $.each($('#controls .actions>div'), function(index, action) { - self.totalWidth += $(action).get(0).offsetWidth; + $.each($('#controls .actions'), function(index, action) { + self.totalWidth += $(action).outerWidth(); }); }, @@ -236,6 +240,6 @@ } }; - window.BreadCrumb = BreadCrumb; + OCA.Files.BreadCrumb = BreadCrumb; })(); diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 963fc64782..6b0ca79368 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -18,7 +18,7 @@ * - TODO music upload button */ -/* global OC, t, n */ +/* global Files, FileList, jQuery, oc_requesttoken, humanFileSize, getUniqueName */ /** * Function that will allow us to know if Ajax uploads are supported @@ -65,7 +65,7 @@ OC.Upload = { */ cancelUploads:function() { this.log('canceling uploads'); - jQuery.each(this._uploads,function(i, jqXHR) { + jQuery.each(this._uploads, function(i, jqXHR) { jqXHR.abort(); }); this._uploads = []; @@ -83,7 +83,7 @@ OC.Upload = { isProcessing:function() { var count = 0; - jQuery.each(this._uploads,function(i, data) { + jQuery.each(this._uploads, function(i, data) { if (data.state() === 'pending') { count++; } @@ -205,14 +205,16 @@ OC.Upload = { */ add: function(e, data) { OC.Upload.log('add', e, data); - var that = $(this); - var freeSpace; + var that = $(this), 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 + // 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 ) { @@ -244,14 +246,15 @@ OC.Upload = { // 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) { + if ( ! file.type && file.size%4096 === 0 && file.size <= 102400) { try { - reader = new FileReader(); - reader.readAsBinaryString(f); + var reader = new FileReader(); + reader.readAsBinaryString(file); } 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', + data.errorThrown = t('files', + 'Unable to upload {filename} as it is a directory or has 0 bytes', {filename: file.name} ); } @@ -263,7 +266,8 @@ OC.Upload = { // 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}', { + data.errorThrown = t('files', + 'Total file size {size1} exceeds upload limit {size2}', { 'size1': humanFileSize(selection.totalBytes), 'size2': humanFileSize($('#upload_limit').val()) }); @@ -273,7 +277,8 @@ OC.Upload = { 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', { + 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()) }); @@ -341,7 +346,7 @@ OC.Upload = { // noone set update parameters, we set the minimum data.formData = { requesttoken: oc_requesttoken, - dir: $('#dir').val(), + dir: FileList.getCurrentDirectory(), file_directory: fileDirectory }; } @@ -384,31 +389,29 @@ OC.Upload = { //fetch response from iframe response = data.result[0].body.innerText; } - var result=$.parseJSON(response); + var result = $.parseJSON(response); delete data.jqXHR; + var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); + 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); } }, @@ -440,7 +443,7 @@ OC.Upload = { fileupload.on('fileuploadstart', function(e, data) { OC.Upload.log('progress handle fileuploadstart', e, data); $('#uploadprogresswrapper input.stop').show(); - $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').progressbar({value: 0}); $('#uploadprogressbar').fadeIn(); }); fileupload.on('fileuploadprogress', function(e, data) { @@ -457,7 +460,6 @@ OC.Upload = { $('#uploadprogresswrapper input.stop').fadeOut(); $('#uploadprogressbar').fadeOut(); - Files.updateStorageStatistics(); }); fileupload.on('fileuploadfail', function(e, data) { OC.Upload.log('progress handle fileuploadfail', e, data); @@ -468,8 +470,6 @@ OC.Upload = { } }); - } else { - console.log('skipping file progress because your browser is broken'); } } @@ -509,7 +509,7 @@ OC.Upload = { $('#new li').each(function(i,element) { if ($(element).children('p').length === 0) { $(element).children('form').remove(); - $(element).append('

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

'); + $(element).append('

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

'); } }); }); @@ -527,16 +527,16 @@ OC.Upload = { $('#new .error').tipsy('hide'); - $('#new li').each(function(i,element) { + $('#new li').each(function(i, element) { if ($(element).children('p').length === 0) { $(element).children('form').remove(); - $(element).append('

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

'); + $(element).append('

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

'); } }); - var type=$(this).data('type'); - var text=$(this).children('p').text(); - $(this).data('text',text); + var type = $(this).data('type'); + var text = $(this).children('p').text(); + $(this).data('text', text); $(this).children('p').remove(); // add input field @@ -553,7 +553,7 @@ OC.Upload = { var filename = input.val(); if (type === 'web' && filename.length === 0) { throw t('files', 'URL cannot be empty'); - } else if (type !== 'web' && !Files.isFileNameValid(filename)) { + } 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}); @@ -592,7 +592,7 @@ OC.Upload = { if (FileList.lastAction) { FileList.lastAction(); } - var name = getUniqueName(newname); + var name = FileList.getUniqueName(newname); if (newname !== name) { FileList.checkName(name, newname, true); var hidden = true; @@ -603,7 +603,10 @@ OC.Upload = { case 'file': $.post( OC.filePath('files', 'ajax', 'newfile.php'), - {dir:$('#dir').val(), filename:name}, + { + dir: FileList.getCurrentDirectory(), + filename: name + }, function(result) { if (result.status === 'success') { FileList.add(result.data, {hidden: hidden, animate: true}); @@ -616,7 +619,10 @@ OC.Upload = { case 'folder': $.post( OC.filePath('files','ajax','newfolder.php'), - {dir:$('#dir').val(), foldername:name}, + { + dir: FileList.getCurrentDirectory(), + foldername: name + }, function(result) { if (result.status === 'success') { FileList.add(result.data, {hidden: hidden, animate: true}); @@ -627,39 +633,46 @@ OC.Upload = { ); break; case 'web': - if (name.substr(0,8) !== 'https://' && name.substr(0,7) !== 'http://') { + 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); + 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(); + if (localName.indexOf('/')) { //use last part of url + localName = localName.split('/').pop(); } else { //or the domain - localName=(localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.',''); + localName = (localName.match(/:\/\/(.[^\/]+)/)[1]).replace('www.', ''); } - localName = getUniqueName(localName); + localName = FileList.getUniqueName(localName); //IE < 10 does not fire the necessary events for the progress bar. if ($('html.lte9').length === 0) { - $('#uploadprogressbar').progressbar({value: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) { + var eventSource = new OC.EventSource( + OC.filePath('files', 'ajax', 'newfile.php'), + { + dir: FileList.getCurrentDirectory(), + 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) { + eventSource.listen('success', function(data) { var file = data; $('#uploadprogressbar').fadeOut(); FileList.add(file, {hidden: hidden, animate: true}); }); - eventSource.listen('error',function(error) { + eventSource.listen('error', function(error) { $('#uploadprogressbar').fadeOut(); var message = (error && error.message) || t('core', 'Error fetching URL'); OC.Notification.show(message); @@ -670,12 +683,12 @@ OC.Upload = { }); break; } - var li=form.parent(); + 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')+'

'); + li.append('

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

'); $('#new>a').click(); } catch (error) { input.attr('title', error); diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index ecdfa72a47..b9cd9816d4 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -8,242 +8,255 @@ * */ -/* global OC, FileList, Files */ /* global trashBinApp */ -var FileActions = { - actions: {}, - defaults: {}, - icons: {}, - currentFile: null, - 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); - } - if (type) {//type is 'dir' or 'file' - if (FileActions.actions[type]) { - actions = $.extend(actions, FileActions.actions[type]); +(function() { + + var FileActions = { + actions: {}, + defaults: {}, + icons: {}, + currentFile: null, + register: function (mime, name, permissions, icon, action, displayName) { + if (!this.actions[mime]) { + this.actions[mime] = {}; } - } - if (mime) { - var mimePart = mime.substr(0, mime.indexOf('/')); - if (FileActions.actions[mimePart]) { - actions = $.extend(actions, FileActions.actions[mimePart]); + if (!this.actions[mime][name]) { + this.actions[mime][name] = {}; } - if (FileActions.actions[mime]) { - actions = $.extend(actions, FileActions.actions[mime]); + if (!displayName) { + displayName = t('files', name); } - } - var filteredActions = {}; - $.each(actions, function (name, action) { - if (action.permissions & permissions) { - filteredActions[name] = action; + this.actions[mime][name]['action'] = action; + this.actions[mime][name]['permissions'] = permissions; + this.actions[mime][name]['displayName'] = displayName; + this.icons[name] = icon; + }, + clear: function() { + this.actions = {}; + this.defaults = {}; + this.icons = {}; + this.currentFile = null; + }, + setDefault: function (mime, name) { + this.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 (this.actions.all) { + actions = $.extend(actions, this.actions.all); } - }); - return filteredActions; - }, - getDefault: function (mime, type, permissions) { - var mimePart; - if (mime) { - mimePart = mime.substr(0, mime.indexOf('/')); - } - var name = false; - if (mime && FileActions.defaults[mime]) { - name = FileActions.defaults[mime]; - } else if (mime && FileActions.defaults[mimePart]) { - name = FileActions.defaults[mimePart]; - } else if (type && FileActions.defaults[type]) { - name = FileActions.defaults[type]; - } else { - name = FileActions.defaults.all; - } - var actions = this.get(mime, type, permissions); - return actions[name]; - }, - /** - * Display file actions for the given element - * @param parent "td" element of the file for which to display actions - * @param triggerEvent if true, triggers the fileActionsReady on the file - * list afterwards (false by default) - */ - display: function (parent, triggerEvent) { - FileActions.currentFile = parent; - var actions = FileActions.getActions(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions()); - var file = FileActions.getCurrentFile(); - var nameLinks; - if (FileList.findFileEl(file).data('renaming')) { - return; - } - - // recreate fileactions - nameLinks = parent.children('a.name'); - nameLinks.find('.fileactions, .nametext .action').remove(); - nameLinks.append(''); - var defaultAction = FileActions.getDefault(FileActions.getCurrentMimeType(), FileActions.getCurrentType(), FileActions.getCurrentPermissions()); - - var actionHandler = function (event) { - event.stopPropagation(); - event.preventDefault(); - - FileActions.currentFile = event.data.elem; - var file = FileActions.getCurrentFile(); - - event.data.actionFunc(file); - }; - - var addAction = function (name, action, displayName) { - - if ((name === 'Download' || action !== defaultAction) && name !== 'Delete') { - - var img = FileActions.icons[name], - actionText = displayName, - actionContainer = 'a.name>span.fileactions'; - - if (name === 'Rename') { - // rename has only an icon which appears behind - // the file name - actionText = ''; - actionContainer = 'a.name span.nametext'; + if (type) {//type is 'dir' or 'file' + if (this.actions[type]) { + actions = $.extend(actions, this.actions[type]); } + } + if (mime) { + var mimePart = mime.substr(0, mime.indexOf('/')); + if (this.actions[mimePart]) { + actions = $.extend(actions, this.actions[mimePart]); + } + if (this.actions[mime]) { + actions = $.extend(actions, this.actions[mime]); + } + } + var filteredActions = {}; + $.each(actions, function (name, action) { + if (action.permissions & permissions) { + filteredActions[name] = action; + } + }); + return filteredActions; + }, + getDefault: function (mime, type, permissions) { + var mimePart; + if (mime) { + mimePart = mime.substr(0, mime.indexOf('/')); + } + var name = false; + if (mime && this.defaults[mime]) { + name = this.defaults[mime]; + } else if (mime && this.defaults[mimePart]) { + name = this.defaults[mimePart]; + } else if (type && this.defaults[type]) { + name = this.defaults[type]; + } else { + name = this.defaults.all; + } + var actions = this.get(mime, type, permissions); + return actions[name]; + }, + /** + * Display file actions for the given element + * @param parent "td" element of the file for which to display actions + * @param triggerEvent if true, triggers the fileActionsReady on the file + * list afterwards (false by default) + */ + display: function (parent, triggerEvent) { + this.currentFile = parent; + var self = this; + var actions = this.getActions(this.getCurrentMimeType(), this.getCurrentType(), this.getCurrentPermissions()); + var file = this.getCurrentFile(); + var nameLinks; + if (parent.closest('tr').data('renaming')) { + return; + } + + // recreate fileactions + nameLinks = parent.children('a.name'); + nameLinks.find('.fileactions, .nametext .action').remove(); + nameLinks.append(''); + var defaultAction = this.getDefault(this.getCurrentMimeType(), this.getCurrentType(), this.getCurrentPermissions()); + + var actionHandler = function (event) { + event.stopPropagation(); + event.preventDefault(); + + self.currentFile = event.data.elem; + var file = self.getCurrentFile(); + + event.data.actionFunc(file); + }; + + var addAction = function (name, action, displayName) { + + if ((name === 'Download' || action !== defaultAction) && name !== 'Delete') { + + var img = self.icons[name], + actionText = displayName, + actionContainer = 'a.name>span.fileactions'; + + if (name === 'Rename') { + // rename has only an icon which appears behind + // the file name + actionText = ''; + actionContainer = 'a.name span.nametext'; + } + if (img.call) { + img = img(file); + } + var html = ''; + if (img) { + html += ''; + } + html += ' ' + actionText + ''; + + var element = $(html); + element.data('action', name); + element.on('click', {a: null, elem: parent, actionFunc: actions[name].action}, actionHandler); + parent.find(actionContainer).append(element); + } + + }; + + $.each(actions, function (name, action) { + if (name !== 'Share') { + displayName = action.displayName; + ah = action.action; + + addAction(name, ah, displayName); + } + }); + if(actions.Share){ + displayName = t('files', 'Share'); + addAction('Share', actions.Share, displayName); + } + + // remove the existing delete action + parent.parent().children().last().find('.action.delete').remove(); + if (actions['Delete']) { + var img = self.icons['Delete']; + var html; if (img.call) { img = img(file); } - var html = ''; - if (img) { - html += ''; + if (typeof trashBinApp !== 'undefined' && trashBinApp) { + html = ''; + } else { + html = ''; } - html += ' ' + actionText + ''; - var element = $(html); - element.data('action', name); - element.on('click', {a: null, elem: parent, actionFunc: actions[name].action}, actionHandler); - parent.find(actionContainer).append(element); + element.data('action', actions['Delete']); + element.on('click', {a: null, elem: parent, actionFunc: actions['Delete'].action}, actionHandler); + parent.parent().children().last().append(element); } - }; - - $.each(actions, function (name, action) { - if (name !== 'Share') { - displayName = action.displayName; - ah = action.action; - - addAction(name, ah, displayName); + if (triggerEvent){ + $('#fileList').trigger(jQuery.Event("fileActionsReady")); } - }); - if(actions.Share){ - displayName = t('files', 'Share'); - addAction('Share', actions.Share, displayName); - } + }, + getCurrentFile: function () { + return this.currentFile.parent().attr('data-file'); + }, + getCurrentMimeType: function () { + return this.currentFile.parent().attr('data-mime'); + }, + getCurrentType: function () { + return this.currentFile.parent().attr('data-type'); + }, + getCurrentPermissions: function () { + return this.currentFile.parent().data('permissions'); + }, - // remove the existing delete action - parent.parent().children().last().find('.action.delete').remove(); - if (actions['Delete']) { - var img = FileActions.icons['Delete']; - var html; - if (img.call) { - img = img(file); - } - if (typeof trashBinApp !== 'undefined' && trashBinApp) { - html = ''; + /** + * Register the actions that are used by default for the files app. + */ + registerDefaultActions: function(fileList) { + // TODO: try to find a way to not make it depend on fileList, + // maybe get a handler or listener to trigger events on + this.register('all', 'Delete', OC.PERMISSION_DELETE, function () { + return OC.imagePath('core', 'actions/delete'); + }, function (filename) { + fileList.do_delete(filename); + $('.tipsy').remove(); + }); + + // t('files', 'Rename') + this.register('all', 'Rename', OC.PERMISSION_UPDATE, function () { + return OC.imagePath('core', 'actions/rename'); + }, function (filename) { + fileList.rename(filename); + }); + + this.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) { + var dir = fileList.getCurrentDirectory(); + if (dir !== '/') { + dir = dir + '/'; + } + fileList.changeDirectory(dir + filename); + }); + + this.setDefault('dir', 'Open'); + var downloadScope; + if ($('#allowZipDownload').val() == 1) { + downloadScope = 'all'; } else { - html = ''; + downloadScope = 'file'; } - var element = $(html); - element.data('action', actions['Delete']); - element.on('click', {a: null, elem: parent, actionFunc: actions['Delete'].action}, actionHandler); - parent.parent().children().last().append(element); + + this.register(downloadScope, 'Download', OC.PERMISSION_READ, function () { + return OC.imagePath('core', 'actions/download'); + }, function (filename) { + var url = OCA.Files.Files.getDownloadUrl(filename, fileList.getCurrentDirectory()); + if (url) { + OC.redirect(url); + } + }); + + fileList.$fileList.trigger(jQuery.Event("fileActionsReady")); } + }; - if (triggerEvent){ - $('#fileList').trigger(jQuery.Event("fileActionsReady")); - } - }, - getCurrentFile: function () { - return FileActions.currentFile.parent().attr('data-file'); - }, - getCurrentMimeType: function () { - return FileActions.currentFile.parent().attr('data-mime'); - }, - getCurrentType: function () { - return FileActions.currentFile.parent().attr('data-type'); - }, - getCurrentPermissions: function () { - return FileActions.currentFile.parent().data('permissions'); - } -}; + OCA.Files.FileActions = FileActions; +})(); -$(document).ready(function () { - var downloadScope; - if ($('#allowZipDownload').val() == 1) { - downloadScope = 'all'; - } else { - downloadScope = 'file'; - } +// for backward compatibility +window.FileActions = OCA.Files.FileActions; - if (typeof disableDownloadActions == 'undefined' || !disableDownloadActions) { - FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () { - return OC.imagePath('core', 'actions/download'); - }, function (filename) { - var url = Files.getDownloadUrl(filename); - if (url) { - OC.redirect(url); - } - }); - } - $('#fileList tr').each(function () { - FileActions.display($(this).children('td.filename')); - }); - - $('#fileList').trigger(jQuery.Event("fileActionsReady")); - -}); - -FileActions.register('all', 'Delete', OC.PERMISSION_DELETE, function () { - return OC.imagePath('core', 'actions/delete'); -}, function (filename) { - FileList.do_delete(filename); - $('.tipsy').remove(); -}); - -// t('files', 'Rename') -FileActions.register('all', 'Rename', OC.PERMISSION_UPDATE, function () { - return OC.imagePath('core', 'actions/rename'); -}, function (filename) { - FileList.rename(filename); -}); - -FileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) { - var dir = $('#dir').val() || '/'; - if (dir !== '/') { - dir = dir + '/'; - } - FileList.changeDirectory(dir + filename); -}); - -FileActions.setDefault('dir', 'Open'); diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 8896a8e23a..38766e2b80 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -8,1540 +8,1770 @@ * */ -/* global OC, t, n, FileList, FileActions, Files, FileSummary, BreadCrumb */ -/* global dragOptions, folderDropOptions */ -window.FileList = { - appName: t('files', 'Files'), - isEmpty: true, - useUndo:true, - $el: $('#filestable'), - $fileList: $('#fileList'), - breadcrumb: null, - +(function() { /** - * Instance of FileSummary + * The FileList class manages a file list view. + * A file list view consists of a controls bar and + * a file list table. */ - fileSummary: null, - initialized: false, + var FileList = function($el, options) { + this.initialize($el, options); + }; + FileList.prototype = { + SORT_INDICATOR_ASC_CLASS: 'icon-triangle-s', + SORT_INDICATOR_DESC_CLASS: 'icon-triangle-n', - // number of files per page - pageSize: 20, + id: 'files', + appName: t('files', 'Files'), + isEmpty: true, + useUndo:true, - /** - * Array of files in the current folder. - * The entries are of file data. - */ - files: [], + /** + * Top-level container with controls and file list + */ + $el: null, - /** - * Map of file id to file data - */ - _selectedFiles: {}, + /** + * Files table + */ + $table: null, - /** - * Summary of selected files. - * Instance of FileSummary. - */ - _selectionSummary: null, + /** + * List of rows (table tbody) + */ + $fileList: 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); - }, + breadcrumb: null, - /** - * Initialize the file list and its components - */ - initialize: function() { - var self = this; - if (this.initialized) { - return; - } + /** + * Instance of FileSummary + */ + fileSummary: null, + initialized: false, - // TODO: FileList should not know about global elements - this.$el = $('#filestable'); - this.$fileList = $('#fileList'); - this.files = []; - this._selectedFiles = {}; - this._selectionSummary = new FileSummary(); + // number of files per page + pageSize: 20, - this.fileSummary = this._createSummary(); + /** + * Array of files in the current folder. + * The entries are of file data. + */ + files: [], - this.breadcrumb = new BreadCrumb({ - onClick: this._onClickBreadCrumb, - onDrop: _.bind(this._onDropOnBreadCrumb, this), - getCrumbUrl: function(part, index) { - return self.linkTo(part.dir); + /** + * File actions handler, defaults to OCA.Files.FileActions + */ + fileActions: null, + + /** + * Map of file id to file data + */ + _selectedFiles: {}, + + /** + * Summary of selected files. + * Instance of FileSummary. + */ + _selectionSummary: null, + + /** + * Sort attribute + */ + _sort: 'name', + + /** + * Sort direction: 'asc' or 'desc' + */ + _sortDirection: 'asc', + + /** + * Sort comparator function for the current sort + */ + _sortComparator: null, + + /** + * Current directory + */ + _currentDirectory: null, + + _dragOptions: null, + _folderDropOptions: null, + + /** + * Initialize the file list and its components + * + * @param $el container element with existing markup for the #controls + * and a table + * @param options map of options, see other parameters + * @param scrollContainer scrollable container, defaults to $(window) + * @param dragOptions drag options, disabled by default + * @param folderDropOptions folder drop options, disabled by default + */ + initialize: function($el, options) { + var self = this; + options = options || {}; + if (this.initialized) { + return; } - }); - $('#controls').prepend(this.breadcrumb.$el); + if (options.dragOptions) { + this._dragOptions = options.dragOptions; + } + if (options.folderDropOptions) { + this._folderDropOptions = options.folderDropOptions; + } - $(window).resize(function() { - // TODO: debounce this ? - var width = $(this).width(); - FileList.breadcrumb.resize(width, false); - }); + this.$el = $el; + this.$container = options.scrollContainer || $(window); + this.$table = $el.find('table:first'); + this.$fileList = $el.find('#fileList'); + this.fileActions = OCA.Files.FileActions; + this.files = []; + this._selectedFiles = {}; + this._selectionSummary = new OCA.Files.FileSummary(); - 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)); - }, + this.fileSummary = this._createSummary(); - /** - * 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); - }, + this.setSort('name', 'asc'); - /** - * 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); + var breadcrumbOptions = { + onClick: _.bind(this._onClickBreadCrumb, this), + getCrumbUrl: function(part) { + return self.linkTo(part.dir); } + }; + // if dropping on folders is allowed, then also allow on breadcrumbs + if (this._folderDropOptions) { + breadcrumbOptions.onDrop = _.bind(this._onDropOnBreadCrumb, this); } - 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); - } - } - } - }, + this.breadcrumb = new OCA.Files.BreadCrumb(breadcrumbOptions); - /** - * 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(); - }, + this.$el.find('#controls').prepend(this.breadcrumb.$el); - /** - * 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(); - }, + this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this)); - /** - * 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 this.$fileList.find('tr').filterAttr('data-file', fileName); - }, - - /** - * 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(); - } - - this.fileSummary.calculate(filesArray); - - FileList.updateSelectionSummary(); - $(window).scrollTop(0); - - this.$fileList.trigger(jQuery.Event("updated")); - }, - /** - * 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": fileData.size, - "data-file": name, - "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(' + icon + '); background-size: 32px;' - }); - - // linkUrl - if (type === 'dir') { - 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(linkElem); - tr.append(td); - - // 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'); - } - - td = $('').attr({ - "class": "filesize", - "style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')' - }).text(simpleSize); - tr.append(td); - - // date column - 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(mtime), - "style": 'color:rgb('+modifiedColor+','+modifiedColor+','+modifiedColor+')' - }).text( relative_modified_date(mtime / 1000) )); - tr.find('.filesize').text(simpleSize); - tr.append(td); - return tr; - }, - - /** - * 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); - } - - // 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); - } - } - - this.isEmpty = false; - this.files.splice(index, 0, fileData); - - if ($tr && options.animate) { - $tr.addClass('appear transparent'); - window.setTimeout(function() { - $tr.removeClass('transparent'); + $(window).resize(function() { + // TODO: debounce this ? + var width = $(this).width(); + self.breadcrumb.resize(width, false); }); - } - // defaults to true if not defined - if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) { - this.fileSummary.add(fileData, true); - this.updateEmptyContent(); - } + 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.on('urlChanged', _.bind(this._onUrlChanged, 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)); - return $tr; - }, + this.setupUploadEvents(); - /** - * 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; + this.$container.on('scroll', _.bind(this._onScroll, this)); + }, - if (fileData.isShareMountPoint) { - permissions = permissions | OC.PERMISSION_UPDATE; - } + /** + * Event handler for when the URL changed + */ + _onUrlChanged: function(e) { + if (e && e.dir) { + this.changeDirectory(e.dir, false, true); + } + }, - if (type === 'dir') { - mime = mime || 'httpd/unix-directory'; - } - var tr = this._createRow( - fileData, - options - ); - var filenameTd = tr.find('td.filename'); - - // TODO: move dragging to FileActions ? - // enable drag only for deletable files - if (permissions & OC.PERMISSION_DELETE) { - filenameTd.draggable(dragOptions); - } - // allow dropping on folders - if (fileData.type === 'dir') { - filenameTd.droppable(folderDropOptions); - } - - 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); + /** + * 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 { - // 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 + ')'); + delete this._selectedFiles[$tr.data('id')]; + this._selectionSummary.remove(data); } - } - 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) - * @param changeUrl false if the URL must not be changed (defaults to true) - * @param {boolean} force set to true to force changing directory - */ - changeDirectory: function(targetDir, changeUrl, force) { - var $dir = $('#dir'), - currentDir = $dir.val() || '/'; - targetDir = targetDir || '/'; - if (!force && currentDir === targetDir) { - return; - } - FileList._setCurrentDir(targetDir, changeUrl); - $('#fileList').trigger( - jQuery.Event('changeDirectory', { - dir: targetDir, - previousDir: currentDir + 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) { + this.fileActions.currentFile = $tr.find('td'); + var mime = this.fileActions.getCurrentMimeType(); + var type = this.fileActions.getCurrentType(); + var permissions = this.fileActions.getCurrentPermissions(); + var action = this.fileActions.getDefault(mime,type, permissions); + if (action) { + event.preventDefault(); + action(filename); + } + } } - )); - this._selectedFiles = {}; - this._selectionSummary.clear(); - this.reload(); - }, - linkTo: function(dir) { - return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); - }, + }, - /** - * 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) { - url = FileList.linkTo(targetDir); - window.history.pushState({dir: targetDir}, '', url); - } - // use URL hash for IE8 - else{ - window.location.hash = '?dir='+ encodeURIComponent(targetDir).replace(/%2F/g, '/'); - } - } - this.breadcrumb.setDirectory(this.getCurrentDirectory()); - }, - /** - * @brief Reloads the file list using ajax call - */ - reload: function() { - FileList.showMask(); - if (FileList._reloadCall) { - FileList._reloadCall.abort(); - } - FileList._reloadCall = $.ajax({ - url: Files.getAjaxUrl('list'), - data: { - dir : $('#dir').val() - }, - error: function(result) { - FileList.reloadCallback(result); - }, - success: function(result) { - FileList.reloadCallback(result); - } - }); - }, - reloadCallback: function(result) { - delete this._reloadCall; - this.hideMask(); - - if (!result || result.status === 'error') { - OC.Notification.show(result.data.message); - return; - } - - if (result.status === 404) { - // go back home - this.changeDirectory('/'); - return; - } - // aborted ? - if (result.status === 0){ - return; - } - - // TODO: should rather return upload file size through - // the files list ajax call - Files.updateStorageStatistics(true); - - if (result.data.permissions) { - this.setDirectoryPermissions(result.data.permissions); - } - - this.setFiles(result.data.files); - }, - setDirectoryPermissions: function(permissions) { - var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; - $('#permissions').val(permissions); - $('.creatable').toggleClass('hidden', !isCreatable); - $('.notCreatable').toggleClass('hidden', isCreatable); - }, - /** - * Shows/hides action buttons - * - * @param show true for enabling, false for disabling - */ - showActions: function(show){ - $('.actions,#file_action_panel').toggleClass('hidden', !show); - if (show){ - // make sure to display according to permissions - 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'); - } - }, - /** - * Enables/disables viewer mode. - * In viewer mode, apps can embed themselves under the controls bar. - * In viewer mode, the actions of the file list will be hidden. - * @param show true for enabling, false for disabling - */ - setViewerMode: function(show){ - this.showActions(!show); - $('#filestable').toggleClass('hidden', show); - }, - /** - * 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); + /** + * 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(); - } - 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(); - // 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); - } + /** + * 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(); + }, - return fileEl; - }, - /** - * 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'), - { - dir: dir, - file: fileName, - target: targetPath + /** + * 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(this.getDownloadUrl(files, dir)); + return false; + }, + + /** + * Event handler for when clicking on "Delete" for the selected files + */ + _onClickDeleteSelected: function(event) { + var files = null; + if (!this.isAllSelected()) { + files = _.pluck(this.getSelectedFiles(), 'name'); + } + this.do_delete(files); + event.preventDefault(); + return false; + }, + + /** + * Event handler when clicking on a table header + */ + _onClickHeader: function(e) { + var $target = $(e.target); + var sort; + if (!$target.is('a')) { + $target = $target.closest('a'); + } + sort = $target.attr('data-sort'); + if (sort) { + if (this._sort === sort) { + this.setSort(sort, (this._sortDirection === 'desc')?'asc':'desc'); + } + else { + this.setSort(sort, 'asc'); + } + this.reload(); + } + }, + + /** + * 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(); + this.changeDirectory($targetDir); + } + }, + + /** + * Event handler for when scrolling the list container. + * This appends/renders the next page of entries when reaching the bottom. + */ + _onScroll: function(e) { + if (this.$container.scrollTop() + this.$container.height() > this.$el.height() - 100) { + 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'), this.elementToFile); + } + + this.move(_.pluck(files, 'name'), targetPath); + }, + + /** + * Sets a new page title + */ + setPageTitle: function(title){ + if (title) { + title += ' - '; + } else { + title = ''; + } + title += this.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 this.$fileList.find('tr').filterAttr('data-file', fileName); + }, + + /** + * 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")); + + this.fileSummary.calculate(filesArray); + + this.updateSelectionSummary(); + $(window).scrollTop(0); + + this.$fileList.trigger(jQuery.Event("updated")); + }, + /** + * 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": fileData.size, + "data-file": name, + "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(' + icon + '); background-size: 32px;' + }); + + // linkUrl + if (type === 'dir') { + linkUrl = this.linkTo(this.getCurrentDirectory() + '/' + name); + } + else { + linkUrl = this.getDownloadUrl(name, this.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(linkElem); + tr.append(td); + + // 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'); + } + + td = $('').attr({ + "class": "filesize", + "style": 'color:rgb(' + sizeColor + ',' + sizeColor + ',' + sizeColor + ')' + }).text(simpleSize); + tr.append(td); + + // date column + 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(mtime), + "style": 'color:rgb('+modifiedColor+','+modifiedColor+','+modifiedColor+')' + }).text( relative_modified_date(mtime / 1000) )); + tr.find('.filesize').text(simpleSize); + tr.append(td); + return tr; + }, + + /** + * 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); + } + + // 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); + } + } + + this.isEmpty = false; + this.files.splice(index, 0, fileData); + + if ($tr && options.animate) { + $tr.addClass('appear transparent'); + window.setTimeout(function() { + $tr.removeClass('transparent'); + }); + } + + // 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'); + + // TODO: move dragging to FileActions ? + // enable drag only for deletable files + if (this._dragOptions && permissions & OC.PERMISSION_DELETE) { + filenameTd.draggable(this._dragOptions); + } + // allow dropping on folders + if (this._folderDropOptions && fileData.type === 'dir') { + filenameTd.droppable(this._folderDropOptions); + } + + if (options.hidden) { + tr.addClass('hidden'); + } + + // display actions + this.fileActions.display(filenameTd, false); + + if (fileData.isPreviewAvailable) { + // lazy load / newly inserted td ? + if (!fileData.icon) { + this.lazyLoadPreview({ + path: this.getCurrentDirectory() + '/' + fileData.name, + mime: mime, + etag: fileData.etag, + callback: function(url) { + filenameTd.css('background-image', 'url(' + url + ')'); + } + }); + } + else { + // set the preview URL directly + var urlSpec = { + file: this.getCurrentDirectory() + '/' + fileData.name, + c: fileData.etag + }; + var previewUrl = this.generatePreviewUrl(urlSpec); + previewUrl = previewUrl.replace('(', '%28').replace(')', '%29'); + filenameTd.css('background-image', 'url(' + previewUrl + ')'); + } + } + return tr; + }, + /** + * Returns the current directory + * @return current directory + */ + getCurrentDirectory: function(){ + return this._currentDirectory || this.$el.find('#dir').val() || '/'; + }, + /** + * Returns the directory permissions + * @return permission value as integer + */ + getDirectoryPermissions: function() { + return parseInt(this.$el.find('#permissions').val(), 10); + }, + /** + * @brief Changes the current directory and reload the file list. + * @param targetDir target directory (non URL encoded) + * @param changeUrl false if the URL must not be changed (defaults to true) + * @param {boolean} force set to true to force changing directory + */ + changeDirectory: function(targetDir, changeUrl, force) { + var currentDir = this.getCurrentDirectory(); + targetDir = targetDir || '/'; + if (!force && currentDir === targetDir) { + return; + } + this._setCurrentDir(targetDir, changeUrl); + this.reload(); + }, + linkTo: function(dir) { + return OC.linkTo('files', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); + }, + + /** + * Sets the file actions handler + */ + setFileActions: function(fileActions) { + this.fileActions = fileActions; + }, + + /** + * 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 previousDir = this.getCurrentDirectory(), + baseDir = OC.basename(targetDir); + + if (baseDir !== '') { + this.setPageTitle(baseDir); + } + else { + this.setPageTitle(); + } + + this._currentDirectory = targetDir; + + // legacy stuff + this.$el.find('#dir').val(targetDir); + + if (changeUrl !== false) { + this.$el.trigger(jQuery.Event('changeDirectory', { + dir: targetDir, + previousDir: previousDir + })); + } + this.breadcrumb.setDirectory(this.getCurrentDirectory()); + }, + /** + * Sets the current sorting and refreshes the list + * + * @param sort sort attribute name + * @param direction sort direction, one of "asc" or "desc" + */ + setSort: function(sort, direction) { + var comparator = FileList.Comparators[sort] || FileList.Comparators.name; + this._sort = sort; + this._sortDirection = (direction === 'desc')?'desc':'asc'; + this._sortComparator = comparator; + if (direction === 'desc') { + this._sortComparator = function(fileInfo1, fileInfo2) { + return -comparator(fileInfo1, fileInfo2); + }; + } + this.$el.find('thead th .sort-indicator') + .removeClass(this.SORT_INDICATOR_ASC_CLASS + ' ' + this.SORT_INDICATOR_DESC_CLASS); + this.$el.find('thead th.column-' + sort + ' .sort-indicator') + .addClass(direction === 'desc' ? this.SORT_INDICATOR_DESC_CLASS : this.SORT_INDICATOR_ASC_CLASS); + }, + /** + * @brief Reloads the file list using ajax call + */ + reload: function() { + var self = this; + this._selectedFiles = {}; + this._selectionSummary.clear(); + this.$el.find('.select-all').prop('checked', false); + this.showMask(); + if (this._reloadCall) { + this._reloadCall.abort(); + } + this._reloadCall = $.ajax({ + url: this.getAjaxUrl('list'), + data: { + dir : this.getCurrentDirectory(), + sort: this._sort, + sortdirection: this._sortDirection }, - 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)); + error: function(result) { + self.reloadCallback(result); + }, + success: function(result) { + self.reloadCallback(result); + } + }); + }, + reloadCallback: function(result) { + delete this._reloadCall; + this.hideMask(); - // TODO: also update entry in FileList.files + if (!result || result.status === 'error') { + OC.Notification.show(result.data.message); + return; + } - self.remove(fileName); + if (result.status === 404) { + // go back home + this.changeDirectory('/'); + return; + } + // aborted ? + if (result.status === 0){ + return; + } + + // TODO: should rather return upload file size through + // the files list ajax call + this.updateStorageStatistics(true); + + if (result.data.permissions) { + this.setDirectoryPermissions(result.data.permissions); + } + + this.setFiles(result.data.files); + }, + + updateStorageStatistics: function(force) { + OCA.Files.Files.updateStorageStatistics(this.getCurrentDirectory(), force); + }, + + getAjaxUrl: function(action, params) { + return OCA.Files.Files.getAjaxUrl(action, params); + }, + + getDownloadUrl: function(files, dir) { + return OCA.Files.Files.getDownloadUrl(files, dir || this.getCurrentDirectory()); + }, + + /** + * Generates a preview URL based on the URL space. + * @param urlSpec map with {x: width, y: height, file: file path} + * @return preview URL + */ + generatePreviewUrl: function(urlSpec) { + urlSpec = urlSpec || {}; + if (!urlSpec.x) { + urlSpec.x = this.$table.data('preview-x') || 36; + } + if (!urlSpec.y) { + urlSpec.y = this.$table.data('preview-y') || 36; + } + urlSpec.y *= window.devicePixelRatio; + urlSpec.x *= window.devicePixelRatio; + urlSpec.forceIcon = 0; + return OC.generateUrl('/core/preview.png?') + $.param(urlSpec); + }, + + /** + * Lazy load a file's preview. + * + * @param path path of the file + * @param mime mime type + * @param callback callback function to call when the image was loaded + * @param etag file etag (for caching) + */ + lazyLoadPreview : function(options) { + var self = this; + var path = options.path; + var mime = options.mime; + var ready = options.callback; + var etag = options.etag; + + // get mime icon url + OCA.Files.Files.getMimeIcon(mime, function(iconURL) { + var previewURL, + urlSpec = {}; + ready(iconURL); // set mimeicon URL + + urlSpec.file = OCA.Files.Files.fixPath(path); + + if (etag){ + // use etag as cache buster + urlSpec.c = etag; + } + else { + console.warn('OCA.Files.FileList.lazyLoadPreview(): missing etag argument'); + } + + previewURL = self.generatePreviewUrl(urlSpec); + previewURL = previewURL.replace('(', '%28'); + previewURL = previewURL.replace(')', '%29'); + + // preload image to prevent delay + // this will make the browser cache the image + var img = new Image(); + img.onload = function(){ + // if loading the preview image failed (no preview for the mimetype) then img.width will < 5 + if (img.width > 5) { + ready(previewURL); + } + }; + img.src = previewURL; + }); + }, + + setDirectoryPermissions: function(permissions) { + var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; + this.$el.find('#permissions').val(permissions); + this.$el.find('.creatable').toggleClass('hidden', !isCreatable); + this.$el.find('.notCreatable').toggleClass('hidden', isCreatable); + }, + /** + * Shows/hides action buttons + * + * @param show true for enabling, false for disabling + */ + showActions: function(show){ + this.$el.find('.actions,#file_action_panel').toggleClass('hidden', !show); + if (show){ + // make sure to display according to permissions + var permissions = this.getDirectoryPermissions(); + var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; + this.$el.find('.creatable').toggleClass('hidden', !isCreatable); + this.$el.find('.notCreatable').toggleClass('hidden', isCreatable); + // remove old style breadcrumbs (some apps might create them) + this.$el.find('#controls .crumb').remove(); + // refresh breadcrumbs in case it was replaced by an app + this.breadcrumb.render(); + } + else{ + this.$el.find('.creatable, .notCreatable').addClass('hidden'); + } + }, + /** + * Enables/disables viewer mode. + * In viewer mode, apps can embed themselves under the controls bar. + * In viewer mode, the actions of the file list will be hidden. + * @param show true for enabling, false for disabling + */ + setViewerMode: function(show){ + this.showActions(!show); + this.$el.find('#filestable').toggleClass('hidden', show); + this.$el.trigger(new $.Event('changeViewerMode', {viewerModeEnabled: show})); + }, + /** + * 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 = this.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 (this._dragOptions && (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(); + // TODO: improve performance on batch update + this.isEmpty = !this.files.length; + if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) { + this.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; + }, + /** + * 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._sortComparator(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'), + { + 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.Notification.hide(); + OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); + } + $td.css('background-image', oldBackgroundImage); + } + ); + }); + + }, + + /** + * 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 self = this; + var tr, td, input, form; + tr = this.findFileEl(oldname); + var oldFileInfo = this.files[tr.index()]; + tr.data('renaming',true); + td = tr.children('td.filename'); + input = $('').val(oldname); + form = $('
'); + form.append(input); + td.children('a.name').hide(); + td.append(form); + input.focus(); + //preselect input + var len = input.val().lastIndexOf('.'); + 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) { + // Files.isFileNameValid(filename) throws an exception itself + OCA.Files.Files.isFileNameValid(filename); + if (self.inList(filename)) { + throw t('files', '{new_name} already exists', {new_name: filename}); + } + } + return true; + }; + + form.submit(function(event) { + event.stopPropagation(); + event.preventDefault(); + try { + var newName = input.val(); + if (newName !== oldname) { + checkInput(); + // mark as loading + td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); + $.ajax({ + url: OC.filePath('files','ajax','rename.php'), + data: { + dir : self.getCurrentDirectory(), + 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')); + fileInfo = oldFileInfo; + } + else { + fileInfo = result.data; + } + // reinsert row + self.files.splice(tr.index(), 1); + tr.remove(); + self.add(fileInfo); + } + }); + } + input.tipsy('hide'); + tr.data('renaming',false); + 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.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('.'))); + } + form.remove(); + self.fileActions.display( tr.find('td.filename'), true); + td.children('a.name').show(); + } catch (error) { + input.attr('title', error); + input.tipsy({gravity: 'w', trigger: 'manual'}); + input.tipsy('show'); + input.addClass('error'); + } + return false; + }); + input.keyup(function(event) { + // verify filename on typing + 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'); + } + if (event.keyCode === 27) { + input.tipsy('hide'); + tr.data('renaming',false); + form.remove(); + td.children('a.name').show(); + } + }); + input.click(function(event) { + event.stopPropagation(); + event.preventDefault(); + }); + input.blur(function() { + form.trigger('submit'); + }); + }, + inList:function(file) { + return this.findFileEl(file).length; + }, + /** + * 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 self = this; + var params; + if (files && files.substr) { + files=[files]; + } + if (files) { + for (var i=0; itd.date .action.delete').removeClass('delete-icon').addClass('progress-icon'); + } + + $.post(OC.filePath('files', 'ajax', 'delete.php'), + params, + function(result) { + if (result.status === 'success') { + if (params.allfiles) { + self.setFiles([]); + } + else { + $.each(files,function(index,file) { + var fileEl = self.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'); + self.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}); + }); + } + // TODO: this info should be returned by the ajax call! + self.updateEmptyContent(); + self.fileSummary.update(); + self.updateSelectionSummary(); + self.updateStorageStatistics(); + } else { if (result.status === 'error' && result.data.message) { OC.Notification.show(result.data.message); } else { - OC.Notification.show(t('files', 'Error moving file.')); + OC.Notification.show(t('files', 'Error deleting 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); - }); - }); - - }, - - /** - * 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); - form = $('
'); - form.append(input); - td.children('a.name').hide(); - td.append(form); - input.focus(); - //preselect input - var len = input.val().lastIndexOf('.'); - 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) { - // Files.isFileNameValid(filename) throws an exception itself - Files.isFileNameValid(filename); - if (FileList.inList(filename)) { - throw t('files', '{new_name} already exists', {new_name: filename}); - } - } - return true; - }; - - form.submit(function(event) { - event.stopPropagation(); - event.preventDefault(); - try { - var newName = input.val(); - if (newName !== oldname) { - checkInput(); - // 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, - file: oldname - }, - success: function(result) { - var fileInfo; - if (!result || result.status === 'error') { - OC.dialogs.alert(result.data.message, t('core', 'Could not rename file')); - fileInfo = oldFileInfo; + if (params.allfiles) { + // reload the page as we don't know what files were deleted + // and which ones remain + self.reload(); } else { - fileInfo = result.data; + $.each(files,function(index,file) { + var deleteAction = self.findFileEl(file).find('.action.delete'); + deleteAction.removeClass('progress-icon').addClass('delete-icon'); + }); } - // reinsert row - FileList.files.splice(tr.index(), 1); - tr.remove(); - FileList.add(fileInfo); } }); - } - input.tipsy('hide'); - tr.data('renaming',false); - 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.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('.'))); - } - form.remove(); - FileActions.display( tr.find('td.filename'), true); - td.children('a.name').show(); - } catch (error) { - input.attr('title', error); - input.tipsy({gravity: 'w', trigger: 'manual'}); - input.tipsy('show'); - input.addClass('error'); - } - return false; - }); - input.keyup(function(event) { - // verify filename on typing - 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'); - } - if (event.keyCode === 27) { - input.tipsy('hide'); - tr.data('renaming',false); - form.remove(); - td.children('a.name').show(); - } - }); - input.click(function(event) { - event.stopPropagation(); - event.preventDefault(); - }); - input.blur(function() { - form.trigger('submit'); - }); - }, - inList:function(file) { - return FileList.findFileEl(file).length; - }, - /** - * 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) { - files=[files]; - } - if (files) { - for (var i=0; i'); + this.$el.find('tfoot').append($tr); - params = { - dir: dir || FileList.getCurrentDirectory() - }; - if (files) { - params.files = JSON.stringify(files); - } - 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'); - } + return new OCA.Files.FileSummary($tr); + }, + updateEmptyContent: function() { + var permissions = this.getDirectoryPermissions(); + var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; + this.$el.find('#emptycontent').toggleClass('hidden', !isCreatable || !this.isEmpty); + this.$el.find('#filestable thead th').toggleClass('hidden', this.isEmpty); + }, + /** + * Shows the loading mask. + * + * @see #hideMask + */ + showMask: function() { + // in case one was shown before + var $mask = this.$el.find('.mask'); + if ($mask.exists()) { + return; + } - $.post(OC.filePath('files', 'ajax', 'delete.php'), - params, - function(result) { - if (result.status === 'success') { - if (params.allfiles) { - FileList.setFiles([]); - } - else { - $.each(files,function(index,file) { - 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')}); - }); - } - // TODO: this info should be returned by the ajax call! - checkTrashStatus(); - FileList.updateEmptyContent(); - FileList.fileSummary.update(); - FileList.updateSelectionSummary(); - Files.updateStorageStatistics(); - } else { - if (result.status === 'error' && result.data.message) { - OC.Notification.show(result.data.message); - } - else { - OC.Notification.show(t('files', 'Error deleting file.')); - } - // hide notification after 10 sec - setTimeout(function() { - OC.Notification.hide(); - }, 10000); - if (params.allfiles) { - // reload the page as we don't know what files were deleted - // and which ones remain - FileList.reload(); - } - else { - $.each(files,function(index,file) { - var deleteAction = FileList.findFileEl(file).find('.action.delete'); - deleteAction.removeClass('progress-icon').addClass('delete-icon'); - }); - } - } + this.$table.addClass('hidden'); + + $mask = $('
'); + + $mask.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')'); + $mask.css('background-repeat', 'no-repeat'); + this.$el.append($mask); + + $mask.removeClass('transparent'); + }, + /** + * Hide the loading mask. + * @see #showMask + */ + hideMask: function() { + this.$el.find('.mask').remove(); + this.$table.removeClass('hidden'); + }, + scrollTo:function(file) { + //scroll to and highlight preselected file + var $scrollToRow = this.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'); }); - }, - /** - * Creates the file summary section - */ - _createSummary: function() { - var $tr = $(''); - this.$el.find('tfoot').append($tr); - - return new FileSummary($tr); - }, - updateEmptyContent: function() { - var permissions = $('#permissions').val(); - var isCreatable = (permissions & OC.PERMISSION_CREATE) !== 0; - $('#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'); - if ($mask.exists()) { - 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); - - $mask.removeClass('transparent'); - }, - /** - * Hide the loading mask. - * @see #showMask - */ - hideMask: function() { - $('#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); - //remove highlight when hovered over - $scrollToRow.one('hover', function() { - $scrollToRow.removeClass('searchresult'); - }); - } - }, - filter:function(query) { - $('#fileList tr').each(function(i,e) { - if ($(e).data('file').toString().toLowerCase().indexOf(query.toLowerCase()) !== -1) { - $(e).addClass("searchresult"); - } else { - $(e).removeClass("searchresult"); } - }); - //do not use scrollto to prevent removing searchresult css class - var first = $('#fileList tr.searchresult').first(); - if (first.exists()) { - $(window).scrollTop(first.position().top); - } - }, - unfilter:function() { - $('#fileList tr.searchresult').each(function(i,e) { - $(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 += ' & '; + }, + filter:function(query) { + this.$fileList.find('tr').each(function(i,e) { + if ($(e).data('file').toString().toLowerCase().indexOf(query.toLowerCase()) !== -1) { + $(e).addClass("searchresult"); + } else { + $(e).removeClass("searchresult"); } + }); + //do not use scrollto to prevent removing searchresult css class + var first = this.$fileList.find('tr.searchresult').first(); + if (first.exists()) { + $(window).scrollTop(first.position().top); } - if (summary.totalFiles > 0) { - selection += n('files', '%n file', '%n files', summary.totalFiles); + }, + unfilter:function() { + this.$fileList.find('tr.searchresult').each(function(i,e) { + $(e).removeClass("searchresult"); + }); + }, + /** + * Update UI based on the current selection + */ + updateSelectionSummary: function() { + var summary = this._selectionSummary.summary; + var canDelete; + if (summary.totalFiles === 0 && summary.totalDirs === 0) { + this.$el.find('#headerName a.name>span:first').text(t('files','Name')); + this.$el.find('#headerSize a>span:first').text(t('files','Size')); + this.$el.find('#modified a>span:first').text(t('files','Modified')); + this.$el.find('table').removeClass('multiselect'); + this.$el.find('.selectedActions').addClass('hidden'); } - $('#headerName span.name').text(selection); - $('#modified').text(''); - $('table').addClass('multiselect'); + else { + canDelete = (this.getDirectoryPermissions() & OC.PERMISSION_DELETE); + this.$el.find('.selectedActions').removeClass('hidden'); + this.$el.find('#headerSize a>span:first').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); + } + this.$el.find('#headerName a.name>span:first').text(selection); + this.$el.find('#modified a>span:first').text(''); + this.$el.find('table').addClass('multiselect'); + this.$el.find('.delete-selected').toggleClass('hidden', !canDelete); + } + }, + + /** + * Returns whether all files are selected + * @return true if all files are selected, false otherwise + */ + isAllSelected: function() { + return this.$el.find('.select-all').prop('checked'); + }, + + /** + * Returns the file info of the selected files + * + * @return array of file names + */ + getSelectedFiles: function() { + return _.values(this._selectedFiles); + }, + + getUniqueName: function(name) { + if (this.findFileEl(name).exists()) { + var numMatch; + var parts=name.split('.'); + var extension = ""; + if (parts.length > 1) { + extension=parts.pop(); + } + var base=parts.join('.'); + numMatch=base.match(/\((\d+)\)/); + var num=2; + if (numMatch && numMatch.length>0) { + num=parseInt(numMatch[numMatch.length-1])+1; + base=base.split('('); + base.pop(); + base=$.trim(base.join('(')); + } + name=base+' ('+num+')'; + if (extension) { + name = name+'.'+extension; + } + // FIXME: ugly recursion + return this.getUniqueName(name); + } + return name; + }, + + /** + * Setup file upload events related to the file-upload plugin + */ + setupUploadEvents: function() { + var self = this; + + // handle upload events + var fileUploadStart = this.$el.find('#file_upload_start'); + + fileUploadStart.on('fileuploaddrop', function(e, data) { + OC.Upload.log('filelist handle fileuploaddrop', e, data); + + var dropTarget = $(e.originalEvent.target).closest('tr, .crumb'); + // check if dropped inside this list at all + if (dropTarget && !self.$el.has(dropTarget).length) { + return false; + } + + if (dropTarget && (dropTarget.data('type') === 'dir' || dropTarget.hasClass('crumb'))) { // drag&drop upload to folder + + // remember as context + data.context = dropTarget; + + var dir = dropTarget.data('file'); + // if from file list, need to prepend parent dir + if (dir) { + var parentDir = self.getCurrentDirectory(); + if (parentDir[parentDir.length - 1] !== '/') { + parentDir += '/'; + } + dir = parentDir + dir; + } + else{ + // read full path from crumb + dir = dropTarget.data('dir') || '/'; + } + + // update folder in form + data.formData = function(form) { + return [ + {name: 'dir', value: dir}, + {name: 'requesttoken', value: oc_requesttoken}, + {name: 'file_directory', value: data.files[0].relativePath} + ]; + }; + } else { + // cancel uploads to current dir if no permission + var isCreatable = (self.getDirectoryPermissions() & OC.PERMISSION_CREATE) !== 0; + if (!isCreatable) { + return false; + } + } + }); + fileUploadStart.on('fileuploadadd', function(e, data) { + OC.Upload.log('filelist handle fileuploadadd', e, data); + + //finish delete if we are uploading a deleted file + if (self.deleteFiles && self.deleteFiles.indexOf(data.files[0].name)!==-1) { + self.finishDelete(null, true); //delete file before continuing + } + + // add ui visualization to existing folder + if (data.context && data.context.data('type') === 'dir') { + // add to existing folder + + // update upload counter ui + var uploadText = data.context.find('.uploadtext'); + var currentUploads = parseInt(uploadText.attr('currentUploads'), 10); + currentUploads += 1; + 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(); + } else { + uploadText.text(translatedText); + } + } + + }); + /* + * when file upload done successfully add row to filelist + * update counter when uploading to sub folder + */ + fileUploadStart.on('fileuploaddone', function(e, data) { + OC.Upload.log('filelist handle fileuploaddone', e, data); + + 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); + + 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'), 10); + currentUploads -= 1; + 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'); + data.context.find('td.filename').attr('style','background-image:url('+img+')'); + uploadText.text(translatedText); + uploadText.hide(); + } else { + uploadText.text(translatedText); + } + + // update folder 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 !== '/' && file.directory !== self.getCurrentDirectory()) { + + var fileDirectory = file.directory.replace('/','').replace(/\/$/, "").split('/'); + + if (fileDirectory.length === 1) { + fileDirectory = fileDirectory[0]; + + // Get the directory + var fd = self.findFileEl(fileDirectory); + if (fd.length === 0) { + var dir = { + name: fileDirectory, + type: 'dir', + mimetype: 'httpd/unix-directory', + permissions: file.permissions, + size: 0, + id: file.parentId + }; + self.add(dir, {insert: true}); + } + } else { + fileDirectory = fileDirectory[0]; + } + + fileDirectory = self.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 + size = t('files', 'Pending'); + if (data.files[0].size>=0) { + size=data.files[0].size; + } + //should the file exist in the list remove it + self.remove(file.name); + + // create new file context + data.context = self.add(file, {animate: true}); + } + } + }); + 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'); + uploadText.parents('td.filename').attr('style','background-image:url('+img+')'); + uploadText.fadeOut(); + uploadText.attr('currentUploads', 0); + } + self.updateStorageStatistics(); + }); + 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'); + uploadText.parents('td.filename').attr('style','background-image:url('+img+')'); + uploadText.fadeOut(); + uploadText.attr('currentUploads', 0); + } + self.updateStorageStatistics(); + }); + } - }, + }; /** - * Returns whether all files are selected - * @return true if all files are selected, false otherwise + * Sort comparators. */ - isAllSelected: function() { - return this.$el.find('#select_all').prop('checked'); - }, + FileList.Comparators = { + /** + * Compares two file infos by name, making directories appear + * first. + * + * @param fileInfo1 file info + * @param fileInfo2 file info + * @return -1 if the first file must appear before the second one, + * 0 if they are identify, 1 otherwise. + */ + name: 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); + }, + /** + * Compares two file infos by size. + * + * @param fileInfo1 file info + * @param fileInfo2 file info + * @return -1 if the first file must appear before the second one, + * 0 if they are identify, 1 otherwise. + */ + size: function(fileInfo1, fileInfo2) { + return fileInfo1.size - fileInfo2.size; + }, + /** + * Compares two file infos by timestamp. + * + * @param fileInfo1 file info + * @param fileInfo2 file info + * @return -1 if the first file must appear before the second one, + * 0 if they are identify, 1 otherwise. + */ + mtime: function(fileInfo1, fileInfo2) { + return fileInfo1.mtime - fileInfo2.mtime; + } + }; - /** - * Returns the file info of the selected files - * - * @return array of file names - */ - getSelectedFiles: function() { - return _.values(this._selectedFiles); - } -}; + OCA.Files.FileList = FileList; +})(); $(document).ready(function() { - FileList.initialize(); - - // handle upload events - var fileUploadStart = $('#file_upload_start'); - - fileUploadStart.on('fileuploaddrop', function(e, data) { - OC.Upload.log('filelist handle fileuploaddrop', e, data); - - var dropTarget = $(e.originalEvent.target).closest('tr, .crumb'); - if (dropTarget && (dropTarget.data('type') === 'dir' || dropTarget.hasClass('crumb'))) { // drag&drop upload to folder - - // remember as context - data.context = dropTarget; - - var dir = dropTarget.data('file'); - // if from file list, need to prepend parent dir - if (dir) { - var parentDir = $('#dir').val() || '/'; - if (parentDir[parentDir.length - 1] !== '/') { - parentDir += '/'; - } - dir = parentDir + dir; - } - else{ - // read full path from crumb - dir = dropTarget.data('dir') || '/'; - } - - // update folder in form - data.formData = function(form) { - return [ - {name: 'dir', value: dir}, - {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; - } - } - }); - fileUploadStart.on('fileuploadadd', function(e, data) { - OC.Upload.log('filelist handle fileuploadadd', e, data); - - //finish delete if we are uploading a deleted file - if (FileList.deleteFiles && FileList.deleteFiles.indexOf(data.files[0].name)!==-1) { - FileList.finishDelete(null, true); //delete file before continuing - } - - // add ui visualization to existing folder - if (data.context && data.context.data('type') === 'dir') { - // add to existing folder - - // update upload counter ui - var uploadText = data.context.find('.uploadtext'); - var currentUploads = parseInt(uploadText.attr('currentUploads'), 10); - currentUploads += 1; - 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(); - } else { - uploadText.text(translatedText); - } - } - - }); - /* - * when file upload done successfully add row to filelist - * update counter when uploading to sub folder - */ - fileUploadStart.on('fileuploaddone', function(e, data) { - OC.Upload.log('filelist handle fileuploaddone', e, data); - - 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); - - 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'), 10); - currentUploads -= 1; - 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'); - data.context.find('td.filename').attr('style','background-image:url('+img+')'); - uploadText.text(translatedText); - uploadText.hide(); - } else { - uploadText.text(translatedText); - } - - // update folder 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 !== '/' && 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 - size = t('files', 'Pending'); - if (data.files[0].size>=0) { - size=data.files[0].size; - } - //should the file exist in the list remove it - FileList.remove(file.name); - - // create new file context - data.context = FileList.add(file, {animate: true}); - } - } - }); - 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'); - uploadText.parents('td.filename').attr('style','background-image:url('+img+')'); - uploadText.fadeOut(); - uploadText.attr('currentUploads', 0); - } - }); - 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'); - uploadText.parents('td.filename').attr('style','background-image:url('+img+')'); - uploadText.fadeOut(); - uploadText.attr('currentUploads', 0); - } - }); - - $('#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')); - }); - }); - $('#notification:first-child').on('click', '.suggest', function() { - var file = $('#notification > span').attr('data-oldName'); - FileList.findFileEl(file).removeClass('hidden'); - OC.Notification.hide(); - }); - $('#notification:first-child').on('click', '.cancel', function() { - if ($('#notification > span').attr('data-isNewFile')) { - FileList.deleteCanceled = false; - FileList.deleteFiles = [$('#notification > span').attr('data-oldName')]; - } - }); - FileList.useUndo=(window.onbeforeunload)?true:false; + // FIXME: unused ? + OCA.Files.FileList.useUndo = (window.onbeforeunload)?true:false; $(window).bind('beforeunload', function () { - if (FileList.lastAction) { - FileList.lastAction(); + if (OCA.Files.FileList.lastAction) { + OCA.Files.FileList.lastAction(); } }); $(window).unload(function () { $(window).trigger('beforeunload'); }); - function decodeQuery(query) { - return query.replace(/\+/g, ' '); - } - - function parseHashQuery() { - var hash = window.location.hash, - pos = hash.indexOf('?'); - if (pos >= 0) { - return hash.substr(pos + 1); - } - return ''; - } - - function parseCurrentDirFromUrl() { - var query = parseHashQuery(), - params; - // try and parse from URL hash first - if (query) { - params = OC.parseQueryString(decodeQuery(query)); - } - // else read from query attributes - if (!params) { - params = OC.parseQueryString(decodeQuery(location.search)); - } - return (params && params.dir) || '/'; - } - - // disable ajax/history API for public app (TODO: until it gets ported) - // 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); - } - }; - - $(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 6d167851e6..92f97f5d3c 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -8,257 +8,296 @@ * */ -/* global OC, t, FileList */ /* global getURLParameter */ -var Files = { - // file space size sync - _updateStorageStatistics: function() { - Files._updateStorageStatisticsTimeout = null; - var currentDir = FileList.getCurrentDirectory(), - state = Files.updateStorageStatistics; - if (state.dir){ - if (state.dir === currentDir) { +/** + * Utility class for file related operations + */ +(function() { + var Files = { + // file space size sync + _updateStorageStatistics: function(currentDir) { + var state = Files.updateStorageStatistics; + if (state.dir){ + if (state.dir === currentDir) { + return; + } + // cancel previous call, as it was for another dir + state.call.abort(); + } + state.dir = currentDir; + state.call = $.getJSON(OC.filePath('files','ajax','getstoragestats.php') + '?dir=' + encodeURIComponent(currentDir),function(response) { + state.dir = null; + state.call = null; + Files.updateMaxUploadFilesize(response); + }); + }, + /** + * Update storage statistics such as free space, max upload, + * etc based on the given directory. + * + * Note this function is debounced to avoid making too + * many ajax calls in a row. + * + * @param dir directory + * @param force whether to force retrieving + */ + updateStorageStatistics: function(dir, force) { + if (!OC.currentUser) { return; } - // cancel previous call, as it was for another dir - state.call.abort(); - } - state.dir = currentDir; - state.call = $.getJSON(OC.filePath('files','ajax','getstoragestats.php') + '?dir=' + encodeURIComponent(currentDir),function(response) { - state.dir = null; - state.call = null; - Files.updateMaxUploadFilesize(response); - }); - }, - updateStorageStatistics: function(force) { - if (!OC.currentUser) { - return; - } - // debounce to prevent calling too often - if (Files._updateStorageStatisticsTimeout) { - clearTimeout(Files._updateStorageStatisticsTimeout); - } - if (force) { - Files._updateStorageStatistics(); - } - else { - Files._updateStorageStatisticsTimeout = setTimeout(Files._updateStorageStatistics, 250); - } - }, - - updateMaxUploadFilesize:function(response) { - if (response === undefined) { - return; - } - if (response.data !== undefined && response.data.uploadMaxFilesize !== undefined) { - $('#max_upload').val(response.data.uploadMaxFilesize); - $('#free_space').val(response.data.freeSpace); - $('#upload.button').attr('original-title', response.data.maxHumanFilesize); - $('#usedSpacePercent').val(response.data.usedSpacePercent); - Files.displayStorageWarnings(); - } - if (response[0] === undefined) { - return; - } - if (response[0].uploadMaxFilesize !== undefined) { - $('#max_upload').val(response[0].uploadMaxFilesize); - $('#upload.button').attr('original-title', response[0].maxHumanFilesize); - $('#usedSpacePercent').val(response[0].usedSpacePercent); - Files.displayStorageWarnings(); - } - - }, - - /** - * Fix path name by removing double slash at the beginning, if any - */ - fixPath: function(fileName) { - if (fileName.substr(0, 2) == '//') { - return fileName.substr(1); - } - return fileName; - }, - - /** - * Checks whether the given file name is valid. - * @param name file name to check - * @return true if the file name is valid. - * Throws a string exception with an error message if - * the file name is not valid - */ - isFileNameValid: function (name) { - var trimmedName = name.trim(); - 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 invalidCharacters = - ['\\', '/', '<', '>', ':', '"', '|', '?', '*', '\n']; - for (var i = 0; i < invalidCharacters.length; i++) { - if (trimmedName.indexOf(invalidCharacters[i]) !== -1) { - throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."); + if (force) { + Files._updateStorageStatistics(dir); } - } - return true; - }, - displayStorageWarnings: function() { - if (!OC.Notification.isHidden()) { - return; - } - - var usedSpacePercent = $('#usedSpacePercent').val(); - if (usedSpacePercent > 98) { - OC.Notification.show(t('files', 'Your storage is full, files can not be updated or synced anymore!')); - return; - } - if (usedSpacePercent > 90) { - OC.Notification.show(t('files', 'Your storage is almost full ({usedSpacePercent}%)', - {usedSpacePercent: usedSpacePercent})); - } - }, - - displayEncryptionWarning: function() { - - if (!OC.Notification.isHidden()) { - return; - } - - var encryptedFiles = $('#encryptedFiles').val(); - var initStatus = $('#encryptionInitStatus').val(); - if (initStatus === '0') { // enc not initialized, but should be - 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.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 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'); - - //drag/drop of files - $fileList.find('tr td.filename').each(function(i,e) { - if ($(e).parent().data('permissions') & OC.PERMISSION_DELETE) { - $(e).draggable(dragOptions); + else { + Files._updateStorageStatisticsDebounced(dir); } - }); + }, - $fileList.find('tr[data-type="dir"] td.filename').each(function(i,e) { - if ($(e).parent().data('permissions') & OC.PERMISSION_CREATE) { - $(e).droppable(folderDropOptions); + updateMaxUploadFilesize:function(response) { + if (response === undefined) { + return; + } + if (response.data !== undefined && response.data.uploadMaxFilesize !== undefined) { + $('#max_upload').val(response.data.uploadMaxFilesize); + $('#free_space').val(response.data.freeSpace); + $('#upload.button').attr('original-title', response.data.maxHumanFilesize); + $('#usedSpacePercent').val(response.data.usedSpacePercent); + Files.displayStorageWarnings(); + } + if (response[0] === undefined) { + return; + } + if (response[0].uploadMaxFilesize !== undefined) { + $('#max_upload').val(response[0].uploadMaxFilesize); + $('#upload.button').attr('original-title', response[0].maxHumanFilesize); + $('#usedSpacePercent').val(response[0].usedSpacePercent); + Files.displayStorageWarnings(); } - }); - }, - /** - * 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); - } - var params = { - dir: dir || FileList.getCurrentDirectory(), - files: filename - }; - return this.getAjaxUrl('download', params); - }, + }, - /** - * 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() { - // FIXME: workaround for trashbin app - if (window.trashBinApp) { - return; - } - Files.displayEncryptionWarning(); - Files.bindKeyboardShortcuts(document, jQuery); + /** + * Fix path name by removing double slash at the beginning, if any + */ + fixPath: function(fileName) { + if (fileName.substr(0, 2) == '//') { + return fileName.substr(1); + } + return fileName; + }, - Files.setupDragAndDrop(); + /** + * Checks whether the given file name is valid. + * @param name file name to check + * @return true if the file name is valid. + * Throws a string exception with an error message if + * the file name is not valid + */ + isFileNameValid: function (name) { + var trimmedName = name.trim(); + 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 invalidCharacters = + ['\\', '/', '<', '>', ':', '"', '|', '?', '*', '\n']; + for (var i = 0; i < invalidCharacters.length; i++) { + if (trimmedName.indexOf(invalidCharacters[i]) !== -1) { + throw t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."); + } + } + return true; + }, + displayStorageWarnings: function() { + if (!OC.Notification.isHidden()) { + return; + } - $('#file_action_panel').attr('activeAction', false); + var usedSpacePercent = $('#usedSpacePercent').val(); + if (usedSpacePercent > 98) { + OC.Notification.show(t('files', 'Your storage is full, files can not be updated or synced anymore!')); + return; + } + if (usedSpacePercent > 90) { + OC.Notification.show(t('files', 'Your storage is almost full ({usedSpacePercent}%)', + {usedSpacePercent: usedSpacePercent})); + } + }, - // Triggers invisible file input - $('#upload a').on('click', function() { - $(this).parent().children('#file_upload_start').trigger('click'); - return false; - }); + displayEncryptionWarning: function() { - // Trigger cancelling of file upload - $('#uploadprogresswrapper .stop').on('click', function() { - OC.Upload.cancelUploads(); - FileList.updateSelectionSummary(); - }); + if (!OC.Notification.isHidden()) { + return; + } - // Show trash bin - $('#trash').on('click', function() { - window.location=OC.filePath('files_trashbin', '', 'index.php'); - }); + var encryptedFiles = $('#encryptedFiles').val(); + var initStatus = $('#encryptionInitStatus').val(); + if (initStatus === '0') { // enc not initialized, but should be + 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.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 was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.')); + return; + } + }, - // 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 - }); + /** + * 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); + } + var params = { + dir: dir, + files: filename + }; + return this.getAjaxUrl('download', params); + }, - //do a background scan if needed - scanFiles(); + /** + * 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; + }, - // display storage warnings - setTimeout(Files.displayStorageWarnings, 100); - OC.Notification.setDefault(Files.displayStorageWarnings); - - // only possible at the moment if user is logged in - if (OC.currentUser) { - // start on load - we ask the server every 5 minutes - var updateStorageStatisticsInterval = 5*60*1000; - var updateStorageStatisticsIntervalId = setInterval(Files.updateStorageStatistics, updateStorageStatisticsInterval); - - // Use jquery-visibility to de-/re-activate file stats sync - if ($.support.pageVisibility) { - $(document).on({ - 'show.visibility': function() { - if (!updateStorageStatisticsIntervalId) { - updateStorageStatisticsIntervalId = setInterval(Files.updateStorageStatistics, updateStorageStatisticsInterval); + 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'; } - }, - 'hide.visibility': function() { - clearInterval(updateStorageStatisticsIntervalId); - updateStorageStatisticsIntervalId = 0; + Files.getMimeIcon.cache[mime]=path; + ready(Files.getMimeIcon.cache[mime]); + }); + } + }, + + /** + * Generates a preview URL based on the URL space. + * @param urlSpec map with {x: width, y: height, file: file path} + * @return preview URL + * @deprecated used OCA.Files.FileList.generatePreviewUrl instead + */ + generatePreviewUrl: function(urlSpec) { + console.warn('DEPRECATED: please use generatePreviewUrl() from an OCA.Files.FileList instance'); + return OCA.Files.App.fileList.generatePreviewUrl(urlSpec); + }, + + /** + * Lazy load preview + * @deprecated used OCA.Files.FileList.lazyLoadPreview instead + */ + lazyLoadPreview : function(path, mime, ready, width, height, etag) { + console.warn('DEPRECATED: please use lazyLoadPreview() from an OCA.Files.FileList instance'); + return OCA.Files.App.fileList.lazyLoadPreview({ + path: path, + mime: mime, + callback: ready, + width: width, + height: height, + etag: etag + }); + }, + + /** + * Initialize the files view + */ + initialize: function() { + Files.getMimeIcon.cache = {}; + Files.displayEncryptionWarning(); + Files.bindKeyboardShortcuts(document, $); + + // TODO: move file list related code (upload) to OCA.Files.FileList + $('#file_action_panel').attr('activeAction', false); + + // Triggers invisible file input + $('#upload a').on('click', function() { + $(this).parent().children('#file_upload_start').trigger('click'); + return false; + }); + + // Trigger cancelling of file upload + $('#uploadprogresswrapper .stop').on('click', function() { + OC.Upload.cancelUploads(); + }); + + // 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(); + + // display storage warnings + setTimeout(Files.displayStorageWarnings, 100); + OC.Notification.setDefault(Files.displayStorageWarnings); + + // only possible at the moment if user is logged in or the files app is loaded + if (OC.currentUser && OCA.Files.App) { + // start on load - we ask the server every 5 minutes + var updateStorageStatisticsInterval = 5*60*1000; + var updateStorageStatisticsIntervalId = setInterval(OCA.Files.App.fileList.updateStorageStatistics, updateStorageStatisticsInterval); + + // TODO: this should also stop when switching to another view + // Use jquery-visibility to de-/re-activate file stats sync + if ($.support.pageVisibility) { + $(document).on({ + 'show.visibility': function() { + if (!updateStorageStatisticsIntervalId) { + updateStorageStatisticsIntervalId = setInterval(OCA.Files.App.fileList.updateStorageStatistics, updateStorageStatisticsInterval); + } + }, + 'hide.visibility': function() { + clearInterval(updateStorageStatisticsIntervalId); + updateStorageStatisticsIntervalId = 0; + } + }); + } + } + + $('#app-settings-header').on('click', function() { + var $settings = $('#app-settings'); + $settings.toggleClass('opened'); + if ($settings.hasClass('opened')) { + $settings.find('input').focus(); } }); + + //scroll to and highlight preselected file + /* + if (getURLParameter('scrollto')) { + FileList.scrollTo(getURLParameter('scrollto')); + } + */ } } - //scroll to and highlight preselected file - if (getURLParameter('scrollto')) { - FileList.scrollTo(getURLParameter('scrollto')); - } -}); + Files._updateStorageStatisticsDebounced = _.debounce(Files._updateStorageStatistics, 250); + OCA.Files.Files = Files; +})(); function scanFiles(force, dir, users) { if (!OC.currentUser) { @@ -292,7 +331,9 @@ function scanFiles(force, dir, users) { scannerEventSource.listen('done',function(count) { scanFiles.scanning=false; console.log('done after ' + count + ' files'); - Files.updateStorageStatistics(); + if (OCA.Files.App) { + OCA.Files.App.fileList.updateStorageStatistics(true); + } }); scannerEventSource.listen('user',function(user) { console.log('scanning files for ' + user); @@ -303,6 +344,7 @@ scanFiles.scanning=false; // TODO: move to FileList var createDragShadow = function(event) { //select dragged file + var FileList = OCA.Files.App.fileList; var isDragSelected = $(event.target).parents('tr').find('td input:first').prop('checked'); if (!isDragSelected) { //select dragged file @@ -311,7 +353,7 @@ var createDragShadow = function(event) { // do not show drag shadow for too many files var selectedFiles = _.first(FileList.getSelectedFiles(), FileList.pageSize); - selectedFiles.sort(FileList._fileInfoCompare); + selectedFiles = _.sortBy(selectedFiles, FileList._fileInfoCompare); if (!isDragSelected && selectedFiles.length === 1) { //revert the selection @@ -323,7 +365,7 @@ var createDragShadow = function(event) { var tbody = $(''); dragshadow.append(tbody); - var dir=$('#dir').val(); + var dir = FileList.getCurrentDirectory(); $(selectedFiles).each(function(i,elem) { var newtr = $('') @@ -336,8 +378,8 @@ var createDragShadow = function(event) { if (elem.type === 'dir') { newtr.find('td.filename').attr('style','background-image:url('+OC.imagePath('core', 'filetypes/folder.png')+')'); } else { - var path = getPathForPreview(elem.name); - Files.lazyLoadPreview(path, elem.mime, function(previewpath) { + var path = dir + '/' + elem.name; + OCA.Files.App.files.lazyLoadPreview(path, elem.mime, function(previewpath) { newtr.find('td.filename').attr('style','background-image:url('+previewpath+')'); }, null, null, elem.etag); } @@ -350,9 +392,14 @@ var createDragShadow = function(event) { //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', + 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){ @@ -383,6 +430,7 @@ var folderDropOptions = { hoverClass: "canDrop", drop: function( event, ui ) { // don't allow moving a file into a selected folder + var FileList = OCA.Files.App.fileList; if ($(event.target).parents('tr').find('td input:first').prop('checked') === true) { return false; } @@ -400,115 +448,11 @@ var folderDropOptions = { tolerance: 'pointer' }; -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]); - }); - } -} -Files.getMimeIcon.cache={}; - -function getPathForPreview(name) { - var path = $('#dir').val() + '/' + 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 previewURL, - urlSpec = {}; - ready(iconURL); // set mimeicon URL - - urlSpec.file = Files.fixPath(path); - - if (etag){ - // use etag as cache buster - urlSpec.c = etag; - } - else { - console.warn('Files.lazyLoadPreview(): missing etag argument'); - } - - previewURL = Files.generatePreviewUrl(urlSpec); - previewURL = previewURL.replace('(', '%28'); - previewURL = previewURL.replace(')', '%29'); - - // preload image to prevent delay - // this will make the browser cache the image - var img = new Image(); - img.onload = function(){ - // if loading the preview image failed (no preview for the mimetype) then img.width will < 5 - if (img.width > 5) { - ready(previewURL); - } - }; - img.src = previewURL; - }); -}; - -function getUniqueName(name) { - if (FileList.findFileEl(name).exists()) { - var numMatch; - var parts=name.split('.'); - var extension = ""; - if (parts.length > 1) { - extension=parts.pop(); - } - var base=parts.join('.'); - numMatch=base.match(/\((\d+)\)/); - var num=2; - if (numMatch && numMatch.length>0) { - num=parseInt(numMatch[numMatch.length-1])+1; - base=base.split('('); - base.pop(); - base=$.trim(base.join('(')); - } - name=base+' ('+num+')'; - if (extension) { - name = name+'.'+extension; - } - return getUniqueName(name); - } - return name; -} - -function checkTrashStatus() { - $.post(OC.filePath('files_trashbin', 'ajax', 'isEmpty.php'), function(result) { - if (result.data.isEmpty === false) { - $("input[type=button][id=trash]").removeAttr("disabled"); - } - }); -} - // override core's fileDownloadPath (legacy) function fileDownloadPath(dir, file) { - return Files.getDownloadUrl(file, dir); + return OCA.Files.Files.getDownloadUrl(file, dir); } +// for backward compatibility +window.Files = OCA.Files.Files; + diff --git a/apps/files/js/filesummary.js b/apps/files/js/filesummary.js index b5130247cc..104dabf1b0 100644 --- a/apps/files/js/filesummary.js +++ b/apps/files/js/filesummary.js @@ -190,6 +190,6 @@ this.$el.append($summary); } }; - window.FileSummary = FileSummary; + OCA.Files.FileSummary = FileSummary; })(); diff --git a/apps/files/js/keyboardshortcuts.js b/apps/files/js/keyboardshortcuts.js index 9d6c3ae8c3..b2f2cd0e58 100644 --- a/apps/files/js/keyboardshortcuts.js +++ b/apps/files/js/keyboardshortcuts.js @@ -12,7 +12,6 @@ * enter: open file/folder * delete/backspace: delete file/folder *****************************/ -var Files = Files || {}; (function(Files) { var keys = []; var keyCodes = { @@ -167,4 +166,4 @@ var Files = Files || {}; removeA(keys, event.keyCode); }); }; -})(Files); +})((OCA.Files && OCA.Files.Files) || {}); diff --git a/apps/files/js/navigation.js b/apps/files/js/navigation.js new file mode 100644 index 0000000000..c58a284e83 --- /dev/null +++ b/apps/files/js/navigation.js @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014 + * + * @author Vincent Petry + * @copyright 2014 Vincent Petry + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +(function() { + + var Navigation = function($el) { + this.initialize($el); + }; + + Navigation.prototype = { + + /** + * Currently selected item in the list + */ + _activeItem: null, + + /** + * Currently selected container + */ + $currentContent: null, + + /** + * Initializes the navigation from the given container + * @param $el element containing the navigation + */ + initialize: function($el) { + this.$el = $el; + this._activeItem = null; + this.$currentContent = null; + this._setupEvents(); + }, + + /** + * Setup UI events + */ + _setupEvents: function() { + this.$el.on('click', 'li a', _.bind(this._onClickItem, this)); + }, + + /** + * Returns the container of the currently active app. + * + * @return app container + */ + getActiveContainer: function() { + return this.$currentContent; + }, + + /** + * Returns the currently active item + * + * @return item ID + */ + getActiveItem: function() { + return this._activeItem; + }, + + /** + * Switch the currently selected item, mark it as selected and + * make the content container visible, if any. + * + * @param string itemId id of the navigation item to select + * @param array options "silent" to not trigger event + */ + setActiveItem: function(itemId, options) { + var oldItemId = this._activeItem; + if (itemId === this._activeItem) { + if (!options || !options.silent) { + this.$el.trigger( + new $.Event('itemChanged', {itemId: itemId, previousItemId: oldItemId}) + ); + } + return; + } + this.$el.find('li').removeClass('selected'); + if (this.$currentContent) { + this.$currentContent.addClass('hidden'); + this.$currentContent.trigger(jQuery.Event('hide')); + } + this._activeItem = itemId; + this.$el.find('li[data-id=' + itemId + ']').addClass('selected'); + this.$currentContent = $('#app-content-' + itemId); + this.$currentContent.removeClass('hidden'); + if (!options || !options.silent) { + this.$currentContent.trigger(jQuery.Event('show')); + this.$el.trigger( + new $.Event('itemChanged', {itemId: itemId, previousItemId: oldItemId}) + ); + } + }, + + /** + * Returns whether a given item exists + */ + itemExists: function(itemId) { + return this.$el.find('li[data-id=' + itemId + ']').length; + }, + + /** + * Event handler for when clicking on an item. + */ + _onClickItem: function(ev) { + var $target = $(ev.target); + var itemId = $target.closest('li').attr('data-id'); + this.setActiveItem(itemId); + return false; + } + }; + + OCA.Files.Navigation = Navigation; + +})(); diff --git a/apps/files/l10n/ar.php b/apps/files/l10n/ar.php index 6779141c5e..ea715c3888 100644 --- a/apps/files/l10n/ar.php +++ b/apps/files/l10n/ar.php @@ -52,12 +52,13 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 = غير محدود", "Maximum input size for ZIP files" => "الحد الأقصى المسموح به لملفات ZIP", "Save" => "حفظ", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "استخدم هذا العنوان لـ الدخول الى ملفاتك عن طريق WebDAV", "New" => "جديد", "Text file" => "ملف", "New folder" => "مجلد جديد", "Folder" => "مجلد", "From link" => "من رابط", -"Deleted files" => "حذف الملفات", "Cancel upload" => "إلغاء رفع الملفات", "Nothing in here. Upload something!" => "لا يوجد شيء هنا. إرفع بعض الملفات!", "Download" => "تحميل", diff --git a/apps/files/l10n/ast.php b/apps/files/l10n/ast.php index a2568ae763..b0ba541778 100644 --- a/apps/files/l10n/ast.php +++ b/apps/files/l10n/ast.php @@ -1,29 +1,67 @@ "Nun pudo movese %s - Yá existe un ficheru con esi nome.", +"Could not move %s" => "Nun pudo movese %s", "File name cannot be empty." => "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.", +"Unable to set upload directory." => "Nun se puede afitar la carpeta de xubida.", +"Invalid Token" => "Token inválidu", "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 upload_max_filesize directive in php.ini: " => "El ficheru xubíu perpasa la direutiva \"upload_max_filesize\" del ficheru php.ini", "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", +"Upload failed. Could not find uploaded file" => "Xubida fallía. Nun se pudo atopar el ficheru xubíu.", +"Upload failed. Could not get file info." => "Falló la xubida. Nun se pudo obtener la información del ficheru.", +"Invalid directory." => "Carpeta non válida.", "Files" => "Ficheros", +"Unable to upload {filename} as it is a directory or has 0 bytes" => "Nun se pudo xubir {filename}, paez que ye un directoriu o tien 0 bytes", +"Upload cancelled." => "Xubida encaboxada.", +"Could not get result from server." => "Nun se pudo obtener el resultáu del servidor.", +"File upload is in progress. Leaving the page now will cancel the upload." => "La xubida del ficheru ta en progresu. Si dexes esta páxina encaboxarase la xubida.", +"{new_name} already exists" => "{new_name} yá existe", "Share" => "Compartir", +"Delete permanently" => "Desaniciar dafechu", "Rename" => "Renomar", +"Your download is being prepared. This might take some time if the files are big." => "Ta preparándose la descarga. Esto podría llevar dalgún tiempu si los ficheros son grandes.", +"Error moving file" => "Fallu moviendo'l ficheru", "Error" => "Fallu", "Name" => "Nome", "Size" => "Tamañu", +"Modified" => "Modificáu", "_%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!" => "L'almacenamientu ta completu, ¡yá nun se pueden anovar o sincronizar ficheros!", +"Your storage is almost full ({usedSpacePercent}%)" => "L'almacenamientu ta casi completu ({usedSpacePercent}%)", +"Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files." => "Deshabilitose'l cifráu pero los tos ficheros tovía tan cifraos. Por favor, vete a los axustes personales pa descrifrar los tos ficheros.", +"%s could not be renamed" => "Nun se puede renomar %s ", +"File handling" => "Alministración de ficheros", +"Maximum upload size" => "Tamañu máximu de xubida", +"max. possible: " => "máx. posible:", +"Needed for multi-file and folder downloads." => "Ye necesariu pa descargues multificheru y de carpetes", +"Enable ZIP-download" => "Activar descarga ZIP", +"0 is unlimited" => "0 ye illimitao", +"Maximum input size for ZIP files" => "Tamañu máximu d'entrada pa ficheros ZIP", "Save" => "Guardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Usa esta direición pa acceder a los ficheros a traviés de WebDAV", +"New" => "Nuevu", +"Text file" => "Ficheru de testu", "New folder" => "Nueva carpeta", "Folder" => "Carpeta", +"From link" => "Dende enllaz", "Cancel upload" => "Encaboxar xuba", +"Nothing in here. Upload something!" => "Nun hai nada equí. ¡Xubi daqué!", "Download" => "Descargar", -"Delete" => "Desaniciar" +"Delete" => "Desaniciar", +"Upload too large" => "La xubida ye demasiao grande", +"The files you are trying to upload exceed the maximum size for file uploads on this server." => "Los ficheros que tas intentando xubir perpasen el tamañu máximu pa les xubíes de ficheros nesti servidor.", +"Files are being scanned, please wait." => "Tan escaniándose los ficheros, espera por favor.", +"Current scanning" => "Escanéu actual" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/bg_BG.php b/apps/files/l10n/bg_BG.php index f9ef3750b5..7b5bac636d 100644 --- a/apps/files/l10n/bg_BG.php +++ b/apps/files/l10n/bg_BG.php @@ -23,6 +23,7 @@ $TRANSLATIONS = array( "Maximum upload size" => "Максимален размер за качване", "0 is unlimited" => "Ползвайте 0 за без ограничения", "Save" => "Запис", +"WebDAV" => "WebDAV", "New" => "Ново", "Text file" => "Текстов файл", "New folder" => "Нова папка", diff --git a/apps/files/l10n/bn_BD.php b/apps/files/l10n/bn_BD.php index b96d2515f1..dd639b4955 100644 --- a/apps/files/l10n/bn_BD.php +++ b/apps/files/l10n/bn_BD.php @@ -35,6 +35,7 @@ $TRANSLATIONS = array( "0 is unlimited" => "০ এর অর্থ অসীম", "Maximum input size for ZIP files" => "ZIP ফাইলের ইনপুটের সর্বোচ্চ আকার", "Save" => "সংরক্ষণ", +"WebDAV" => "WebDAV", "New" => "নতুন", "Text file" => "টেক্সট ফাইল", "Folder" => "ফোল্ডার", diff --git a/apps/files/l10n/ca.php b/apps/files/l10n/ca.php index 6226168175..240e61bfd9 100644 --- a/apps/files/l10n/ca.php +++ b/apps/files/l10n/ca.php @@ -44,6 +44,7 @@ $TRANSLATIONS = array( "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 moving file" => "Error en moure el fitxer", "Error" => "Error", "Could not rename file" => "No es pot canviar el nom de fitxer", @@ -70,13 +71,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 és sense límit", "Maximum input size for ZIP files" => "Mida màxima d'entrada per fitxers ZIP", "Save" => "Desa", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Useu aquesta adreça per accedir als fitxers via WebDAV", "New" => "Nou", "New text file" => "Nou fitxer de text", "Text file" => "Fitxer de text", "New folder" => "Carpeta nova", "Folder" => "Carpeta", "From link" => "Des d'enllaç", -"Deleted files" => "Fitxers esborrats", "Cancel upload" => "Cancel·la la pujada", "You don’t have permission to upload or create files here" => "No teniu permisos per a pujar o crear els fitxers aquí", "Nothing in here. Upload something!" => "Res per aquí. Pugeu alguna cosa!", diff --git a/apps/files/l10n/cs_CZ.php b/apps/files/l10n/cs_CZ.php index 8fa0bb2137..1af95dc7fe 100644 --- a/apps/files/l10n/cs_CZ.php +++ b/apps/files/l10n/cs_CZ.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 znamená bez omezení", "Maximum input size for ZIP files" => "Maximální velikost vstupu pro ZIP soubory", "Save" => "Uložit", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Použijte tuto adresu pro přístup k vašim souborům přes WebDAV", "New" => "Nový", "New text file" => "Nový textový soubor", "Text file" => "Textový soubor", "New folder" => "Nová složka", "Folder" => "Složka", "From link" => "Z odkazu", -"Deleted files" => "Odstraněné soubory", "Cancel upload" => "Zrušit odesílání", "You don’t have permission to upload or create files here" => "Nemáte oprávnění zde nahrávat či vytvářet soubory", "Nothing in here. Upload something!" => "Žádný obsah. Nahrajte něco.", diff --git a/apps/files/l10n/cy_GB.php b/apps/files/l10n/cy_GB.php index 6ed94e5c77..6b4796c3e9 100644 --- a/apps/files/l10n/cy_GB.php +++ b/apps/files/l10n/cy_GB.php @@ -44,7 +44,6 @@ $TRANSLATIONS = array( "Text file" => "Ffeil destun", "Folder" => "Plygell", "From link" => "Dolen o", -"Deleted files" => "Ffeiliau ddilewyd", "Cancel upload" => "Diddymu llwytho i fyny", "Nothing in here. Upload something!" => "Does dim byd fan hyn. Llwythwch rhywbeth i fyny!", "Download" => "Llwytho i lawr", diff --git a/apps/files/l10n/da.php b/apps/files/l10n/da.php index 076fa46b4c..1f73fb89f4 100644 --- a/apps/files/l10n/da.php +++ b/apps/files/l10n/da.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 er ubegrænset", "Maximum input size for ZIP files" => "Maksimal størrelse på ZIP filer", "Save" => "Gem", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Brug denne adresse for at tilgå dine filer via WebDAV", "New" => "Ny", "New text file" => "Ny tekstfil", "Text file" => "Tekstfil", "New folder" => "Ny Mappe", "Folder" => "Mappe", "From link" => "Fra link", -"Deleted files" => "Slettede filer", "Cancel upload" => "Fortryd upload", "You don’t have permission to upload or create files here" => "Du har ikke tilladelse til at uploade eller oprette filer her", "Nothing in here. Upload something!" => "Her er tomt. Upload noget!", diff --git a/apps/files/l10n/de.php b/apps/files/l10n/de.php index 8ad0f8909f..a1472b6e09 100644 --- a/apps/files/l10n/de.php +++ b/apps/files/l10n/de.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "Upload failed. Could not get file info." => "Hochladen fehlgeschlagen. Dateiinformationen konnten nicht abgerufen werden.", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", +"All files" => "Alle 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", "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.", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 bedeutet unbegrenzt", "Maximum input size for ZIP files" => "Maximale Größe für ZIP-Dateien", "Save" => "Speichern", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Verwenden Sie diese Adresse, um via WebDAV auf Ihre Dateien zuzugreifen", "New" => "Neu", "New text file" => "Neue Textdatei", "Text file" => "Textdatei", "New folder" => "Neuer Ordner", "Folder" => "Ordner", "From link" => "Von einem Link", -"Deleted files" => "Gelöschte Dateien", "Cancel upload" => "Upload abbrechen", "You don’t have permission to upload or create files here" => "Du besitzt hier keine Berechtigung, um Dateien hochzuladen oder zu erstellen", "Nothing in here. Upload something!" => "Alles leer. Lade etwas hoch!", diff --git a/apps/files/l10n/de_CH.php b/apps/files/l10n/de_CH.php index 625b9387b0..fc80bfdc7d 100644 --- a/apps/files/l10n/de_CH.php +++ b/apps/files/l10n/de_CH.php @@ -44,12 +44,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 bedeutet unbegrenzt", "Maximum input size for ZIP files" => "Maximale Grösse für ZIP-Dateien", "Save" => "Speichern", +"WebDAV" => "WebDAV", "New" => "Neu", "Text file" => "Textdatei", "New folder" => "Neues Verzeichnis", "Folder" => "Ordner", "From link" => "Von einem Link", -"Deleted files" => "Gelöschte Dateien", "Cancel upload" => "Upload abbrechen", "Nothing in here. Upload something!" => "Alles leer. Laden Sie etwas hoch!", "Download" => "Herunterladen", diff --git a/apps/files/l10n/de_DE.php b/apps/files/l10n/de_DE.php index 9a834f1cc3..d94361a676 100644 --- a/apps/files/l10n/de_DE.php +++ b/apps/files/l10n/de_DE.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "Upload failed. Could not get file info." => "Hochladen fehlgeschlagen. Die Dateiinformationen konnten nicht abgerufen werden.", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", +"All files" => "Alle 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", "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.", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 bedeutet unbegrenzt", "Maximum input size for ZIP files" => "Maximale Größe für ZIP-Dateien", "Save" => "Speichern", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Verwenden Sie diese Adresse, um via WebDAV auf Ihre Dateien zuzugreifen", "New" => "Neu", "New text file" => "Neue Textdatei", "Text file" => "Textdatei", "New folder" => "Neuer Ordner", "Folder" => "Ordner", "From link" => "Von einem Link", -"Deleted files" => "Gelöschte Dateien", "Cancel upload" => "Upload abbrechen", "You don’t have permission to upload or create files here" => "Sie besitzen hier keine Berechtigung Dateien hochzuladen oder zu erstellen", "Nothing in here. Upload something!" => "Alles leer. Laden Sie etwas hoch!", diff --git a/apps/files/l10n/el.php b/apps/files/l10n/el.php index 5ba92033d1..8929263681 100644 --- a/apps/files/l10n/el.php +++ b/apps/files/l10n/el.php @@ -44,6 +44,7 @@ $TRANSLATIONS = array( "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" => "Αδυναμία μετονομασίας αρχείου", @@ -71,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 για απεριόριστο", "Maximum input size for ZIP files" => "Μέγιστο μέγεθος για αρχεία ZIP", "Save" => "Αποθήκευση", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Χρησιμοποιήστε αυτήν την διεύθυνση για να αποκτήσετε πρόσβαση στα αρχεία σας μέσω WebDAV", "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!" => "Δεν υπάρχει τίποτα εδώ. Ανεβάστε κάτι!", diff --git a/apps/files/l10n/en_GB.php b/apps/files/l10n/en_GB.php index 5ebc141b80..e64b7f4cc9 100644 --- a/apps/files/l10n/en_GB.php +++ b/apps/files/l10n/en_GB.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 is unlimited", "Maximum input size for ZIP files" => "Maximum input size for ZIP files", "Save" => "Save", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Use this address to access your Files via WebDAV", "New" => "New", "New text file" => "New text file", "Text file" => "Text file", "New folder" => "New folder", "Folder" => "Folder", "From link" => "From link", -"Deleted files" => "Deleted files", "Cancel upload" => "Cancel upload", "You don’t have permission to upload or create files here" => "You don’t have permission to upload or create files here", "Nothing in here. Upload something!" => "Nothing in here. Upload something!", diff --git a/apps/files/l10n/eo.php b/apps/files/l10n/eo.php index eebd94abc3..9aaf72d98a 100644 --- a/apps/files/l10n/eo.php +++ b/apps/files/l10n/eo.php @@ -58,12 +58,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 signifas senlime", "Maximum input size for ZIP files" => "Maksimuma enirgrando por ZIP-dosieroj", "Save" => "Konservi", +"WebDAV" => "WebDAV", "New" => "Nova", "Text file" => "Tekstodosiero", "New folder" => "Nova dosierujo", "Folder" => "Dosierujo", "From link" => "El ligilo", -"Deleted files" => "Forigitaj dosieroj", "Cancel upload" => "Nuligi alŝuton", "You don’t have permission to upload or create files here" => "Vi ne havas permeson alŝuti aŭ krei dosierojn ĉi tie", "Nothing in here. Upload something!" => "Nenio estas ĉi tie. Alŝutu ion!", diff --git a/apps/files/l10n/es.php b/apps/files/l10n/es.php index ba115e6af7..0a56a324a2 100644 --- a/apps/files/l10n/es.php +++ b/apps/files/l10n/es.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "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", +"All files" => "Todos los 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", "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}", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 significa ilimitado", "Maximum input size for ZIP files" => "Tamaño máximo para archivos ZIP de entrada", "Save" => "Guardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Use esta URL para acceder via WebDAV", "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 eliminados", "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 aquí. ¡Suba algo!", diff --git a/apps/files/l10n/es_AR.php b/apps/files/l10n/es_AR.php index 7d1eb0fb4a..9edbe50206 100644 --- a/apps/files/l10n/es_AR.php +++ b/apps/files/l10n/es_AR.php @@ -65,13 +65,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 significa ilimitado", "Maximum input size for ZIP files" => "Tamaño máximo para archivos ZIP de entrada", "Save" => "Guardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Usar esta dirección para acceder a tus archivos vía WebDAV", "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!", diff --git a/apps/files/l10n/es_BO.php b/apps/files/l10n/es_BO.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/es_BO.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_CL.php b/apps/files/l10n/es_CL.php index fa856ad529..bdefea1d8c 100644 --- a/apps/files/l10n/es_CL.php +++ b/apps/files/l10n/es_CL.php @@ -8,6 +8,7 @@ $TRANSLATIONS = array( "_%n file_::_%n files_" => array("",""), "_Uploading %n file_::_Uploading %n files_" => array("",""), "New folder" => "Nuevo directorio", +"Cancel upload" => "cancelar subida", "Download" => "Descargar" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/es_CO.php b/apps/files/l10n/es_CO.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/es_CO.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_EC.php b/apps/files/l10n/es_EC.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/es_EC.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 b6d06d9413..5b88655631 100644 --- a/apps/files/l10n/es_MX.php +++ b/apps/files/l10n/es_MX.php @@ -65,13 +65,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 significa ilimitado", "Maximum input size for ZIP files" => "Tamaño máximo para archivos ZIP de entrada", "Save" => "Guardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Utilice esta dirección para acceder a sus archivos vía WebDAV", "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 eliminados", "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 aquí. ¡Suba algo!", diff --git a/apps/files/l10n/es_PE.php b/apps/files/l10n/es_PE.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/es_PE.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_UY.php b/apps/files/l10n/es_UY.php new file mode 100644 index 0000000000..0157af093e --- /dev/null +++ b/apps/files/l10n/es_UY.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/et_EE.php b/apps/files/l10n/et_EE.php index 4956e3fb45..783152aa58 100644 --- a/apps/files/l10n/et_EE.php +++ b/apps/files/l10n/et_EE.php @@ -71,13 +71,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 tähendab piiramatut", "Maximum input size for ZIP files" => "Maksimaalne ZIP-faili sisestatava faili suurus", "Save" => "Salvesta", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Kasuta seda aadressi oma failidele ligipääsuks WebDAV kaudu", "New" => "Uus", "New text file" => "Uus tekstifail", "Text file" => "Tekstifail", "New folder" => "Uus kaust", "Folder" => "Kaust", "From link" => "Allikast", -"Deleted files" => "Kustutatud failid", "Cancel upload" => "Tühista üleslaadimine", "You don’t have permission to upload or create files here" => "Sul puuduvad õigused siia failide üleslaadimiseks või tekitamiseks", "Nothing in here. Upload something!" => "Siin pole midagi. Lae midagi üles!", diff --git a/apps/files/l10n/eu.php b/apps/files/l10n/eu.php index 914518151d..c3909ac5da 100644 --- a/apps/files/l10n/eu.php +++ b/apps/files/l10n/eu.php @@ -3,7 +3,9 @@ $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.", +"\"%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", @@ -27,6 +29,8 @@ $TRANSLATIONS = array( "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", +"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.", @@ -40,6 +44,7 @@ $TRANSLATIONS = array( "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", @@ -50,6 +55,7 @@ $TRANSLATIONS = array( "_%n folder_::_%n folders_" => array("karpeta %n","%n karpeta"), "_%n file_::_%n files_" => array("fitxategi %n","%n fitxategi"), "_Uploading %n file_::_Uploading %n files_" => array("Fitxategi %n igotzen","%n fitxategi igotzen"), +"\"{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", @@ -57,6 +63,7 @@ $TRANSLATIONS = array( "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.", "{dirs} and {files}" => "{dirs} eta {files}", "%s could not be renamed" => "%s ezin da berrizendatu", +"Upload (max. %s)" => "Igo (max. %s)", "File handling" => "Fitxategien kudeaketa", "Maximum upload size" => "Igo daitekeen gehienezko tamaina", "max. possible: " => "max, posiblea:", @@ -65,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 mugarik gabe esan nahi du", "Maximum input size for ZIP files" => "ZIP fitxategien gehienezko tamaina", "Save" => "Gorde", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "helbidea erabili zure fitxategiak WebDAV bidez eskuratzeko", "New" => "Berria", "New text file" => "Testu fitxategi berria", "Text file" => "Testu fitxategia", "New folder" => "Karpeta berria", "Folder" => "Karpeta", "From link" => "Estekatik", -"Deleted files" => "Ezabatutako fitxategiak", "Cancel upload" => "Ezeztatu igoera", "You don’t have permission to upload or create files here" => "Ez duzu fitxategiak hona igotzeko edo hemen sortzeko baimenik", "Nothing in here. Upload something!" => "Ez dago ezer. Igo zerbait!", diff --git a/apps/files/l10n/fa.php b/apps/files/l10n/fa.php index ce4efe00e2..01f2905366 100644 --- a/apps/files/l10n/fa.php +++ b/apps/files/l10n/fa.php @@ -43,12 +43,13 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 نامحدود است", "Maximum input size for ZIP files" => "حداکثرمقدار برای بار گزاری پرونده های فشرده", "Save" => "ذخیره", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "از این آدرس استفاده کنید تا بتوانید به فایل‌های خود توسط WebDAV دسترسی پیدا کنید", "New" => "جدید", "Text file" => "فایل متنی", "New folder" => "پوشه جدید", "Folder" => "پوشه", "From link" => "از پیوند", -"Deleted files" => "فایل های حذف شده", "Cancel upload" => "متوقف کردن بار گذاری", "Nothing in here. Upload something!" => "اینجا هیچ چیز نیست.", "Download" => "دانلود", diff --git a/apps/files/l10n/fi_FI.php b/apps/files/l10n/fi_FI.php index 2a5c02277f..c25fe7e1e2 100644 --- a/apps/files/l10n/fi_FI.php +++ b/apps/files/l10n/fi_FI.php @@ -27,6 +27,7 @@ $TRANSLATIONS = array( "Upload failed. Could not get file info." => "Lähetys epäonnistui. Lähettävää tiedostoa ei löydetty.", "Invalid directory." => "Virheellinen kansio.", "Files" => "Tiedostot", +"All files" => "Kaikki 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", "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ä", @@ -71,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 on rajoittamaton", "Maximum input size for ZIP files" => "ZIP-tiedostojen enimmäiskoko", "Save" => "Tallenna", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Käytä tätä osoitetta käyttääksesi tiedostojasi WebDAVin kautta", "New" => "Uusi", "New text file" => "Uusi tekstitiedosto", "Text file" => "Tekstitiedosto", "New folder" => "Uusi kansio", "Folder" => "Kansio", "From link" => "Linkistä", -"Deleted files" => "Poistetut tiedostot", "Cancel upload" => "Peru lähetys", "You don’t have permission to upload or create files here" => "Käyttöoikeutesi eivät riitä tiedostojen lähettämiseen tai kansioiden luomiseen tähän sijaintiin", "Nothing in here. Upload something!" => "Täällä ei ole mitään. Lähetä tänne jotakin!", diff --git a/apps/files/l10n/fr.php b/apps/files/l10n/fr.php index 3e61c782a5..1ddb94d083 100644 --- a/apps/files/l10n/fr.php +++ b/apps/files/l10n/fr.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 est illimité", "Maximum input size for ZIP files" => "Taille maximale pour les fichiers ZIP", "Save" => "Sauvegarder", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Utiliser cette adresse pour accéder à vos fichiers par WebDAV", "New" => "Nouveau", "New text file" => "Nouveau fichier texte", "Text file" => "Fichier texte", "New folder" => "Nouveau dossier", "Folder" => "Dossier", "From link" => "Depuis le lien", -"Deleted files" => "Fichiers supprimés", "Cancel upload" => "Annuler l'envoi", "You don’t have permission to upload or create files here" => "Vous n'avez pas la permission de téléverser ou de créer des fichiers ici", "Nothing in here. Upload something!" => "Il n'y a rien ici ! Envoyez donc quelque chose :)", diff --git a/apps/files/l10n/gl.php b/apps/files/l10n/gl.php index 66d981c454..98a3a73b29 100644 --- a/apps/files/l10n/gl.php +++ b/apps/files/l10n/gl.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "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", +"All files" => "Todos os 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", "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}", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 significa ilimitado", "Maximum input size for ZIP files" => "Tamaño máximo de descarga para os ficheiros ZIP", "Save" => "Gardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Empregue esta ligazón para acceder aos seus ficheiros mediante WebDAV", "New" => "Novo", "New text file" => "Ficheiro novo de texto", "Text file" => "Ficheiro de texto", "New folder" => "Novo cartafol", "Folder" => "Cartafol", "From link" => "Desde a ligazón", -"Deleted files" => "Ficheiros eliminados", "Cancel upload" => "Cancelar o envío", "You don’t have permission to upload or create files here" => "Non ten permisos para enviar ou crear ficheiros aquí.", "Nothing in here. Upload something!" => "Aquí non hai nada. Envíe algo.", diff --git a/apps/files/l10n/he.php b/apps/files/l10n/he.php index 7f15517654..e69599694e 100644 --- a/apps/files/l10n/he.php +++ b/apps/files/l10n/he.php @@ -40,11 +40,11 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 - ללא הגבלה", "Maximum input size for ZIP files" => "גודל הקלט המרבי לקובצי ZIP", "Save" => "שמירה", +"WebDAV" => "WebDAV", "New" => "חדש", "Text file" => "קובץ טקסט", "Folder" => "תיקייה", "From link" => "מקישור", -"Deleted files" => "קבצים שנמחקו", "Cancel upload" => "ביטול ההעלאה", "Nothing in here. Upload something!" => "אין כאן שום דבר. אולי ברצונך להעלות משהו?", "Download" => "הורדה", diff --git a/apps/files/l10n/hu_HU.php b/apps/files/l10n/hu_HU.php index 3cfb547261..89264c0c52 100644 --- a/apps/files/l10n/hu_HU.php +++ b/apps/files/l10n/hu_HU.php @@ -65,13 +65,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 = korlátlan", "Maximum input size for ZIP files" => "ZIP-fájlok maximális kiindulási mérete", "Save" => "Mentés", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Ezt a címet használd, hogy hozzáférj a fileokhoz WebDAV-on keresztül", "New" => "Új", "New text file" => "Új szöveges file", "Text file" => "Szövegfájl", "New folder" => "Új mappa", "Folder" => "Mappa", "From link" => "Feltöltés linkről", -"Deleted files" => "Törölt fájlok", "Cancel upload" => "A feltöltés megszakítása", "You don’t have permission to upload or create files here" => "Önnek nincs jogosultsága ahhoz, hogy ide állományokat töltsön föl, vagy itt újakat hozzon létre", "Nothing in here. Upload something!" => "Itt nincs semmi. Töltsön fel valamit!", diff --git a/apps/files/l10n/id.php b/apps/files/l10n/id.php index e4a2529e5e..4e9852cd18 100644 --- a/apps/files/l10n/id.php +++ b/apps/files/l10n/id.php @@ -63,13 +63,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 berarti tidak terbatas", "Maximum input size for ZIP files" => "Ukuran masukan maksimum untuk berkas ZIP", "Save" => "Simpan", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Gunakan alamat ini untuk mengakses Berkas via WebDAV", "New" => "Baru", "New text file" => "Berkas teks baru", "Text file" => "Berkas teks", "New folder" => "Map baru", "Folder" => "Folder", "From link" => "Dari tautan", -"Deleted files" => "Berkas yang dihapus", "Cancel upload" => "Batal pengunggahan", "You don’t have permission to upload or create files here" => "Anda tidak memiliki akses untuk mengunggah atau membuat berkas disini", "Nothing in here. Upload something!" => "Tidak ada apa-apa di sini. Unggah sesuatu!", diff --git a/apps/files/l10n/is.php b/apps/files/l10n/is.php index 82b3db81d6..982c6f3742 100644 --- a/apps/files/l10n/is.php +++ b/apps/files/l10n/is.php @@ -35,6 +35,7 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 er ótakmarkað", "Maximum input size for ZIP files" => "Hámarks inntaksstærð fyrir ZIP skrár", "Save" => "Vista", +"WebDAV" => "WebDAV", "New" => "Nýtt", "Text file" => "Texta skrá", "Folder" => "Mappa", diff --git a/apps/files/l10n/it.php b/apps/files/l10n/it.php index d55c800916..e4fed8fd2f 100644 --- a/apps/files/l10n/it.php +++ b/apps/files/l10n/it.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "Upload failed. Could not get file info." => "Caricamento non riuscito. Impossibile ottenere informazioni sul file.", "Invalid directory." => "Cartella non valida.", "Files" => "File", +"All files" => "Tutti i 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.", "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}", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 è illimitato", "Maximum input size for ZIP files" => "Dimensione massima per i file ZIP", "Save" => "Salva", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Utilizza questo indirizzo per accedere ai tuoi file con WebDAV", "New" => "Nuovo", "New text file" => "Nuovo file di testo", "Text file" => "File di testo", "New folder" => "Nuova cartella", "Folder" => "Cartella", "From link" => "Da collegamento", -"Deleted files" => "File eliminati", "Cancel upload" => "Annulla invio", "You don’t have permission to upload or create files here" => "Qui non hai i permessi di caricare o creare file", "Nothing in here. Upload something!" => "Non c'è niente qui. Carica qualcosa!", diff --git a/apps/files/l10n/ja.php b/apps/files/l10n/ja.php index 0b00594d71..dfbc590d0a 100644 --- a/apps/files/l10n/ja.php +++ b/apps/files/l10n/ja.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0を指定した場合は無制限", "Maximum input size for ZIP files" => "ZIPファイルでの最大入力サイズ", "Save" => "保存", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "WebDAV 経由でファイルにアクセス するにはこのアドレスを利用してください", "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!" => "ここには何もありません。何かアップロードしてください。", diff --git a/apps/files/l10n/ka_GE.php b/apps/files/l10n/ka_GE.php index d9f5244fa7..b13a6ac23c 100644 --- a/apps/files/l10n/ka_GE.php +++ b/apps/files/l10n/ka_GE.php @@ -40,12 +40,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 is unlimited", "Maximum input size for ZIP files" => "ZIP ფაილების მაქსიმუმ დასაშვები ზომა", "Save" => "შენახვა", +"WebDAV" => "WebDAV", "New" => "ახალი", "Text file" => "ტექსტური ფაილი", "New folder" => "ახალი ფოლდერი", "Folder" => "საქაღალდე", "From link" => "მისამართიდან", -"Deleted files" => "წაშლილი ფაილები", "Cancel upload" => "ატვირთვის გაუქმება", "Nothing in here. Upload something!" => "აქ არაფერი არ არის. ატვირთე რამე!", "Download" => "ჩამოტვირთვა", diff --git a/apps/files/l10n/km.php b/apps/files/l10n/km.php index 08b29304c1..3cfb33854b 100644 --- a/apps/files/l10n/km.php +++ b/apps/files/l10n/km.php @@ -1,17 +1,37 @@ "ឈ្មោះ​ឯកសារ​មិន​អាច​នៅ​ទទេ​បាន​ឡើយ។", +"Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "ឈ្មោះ​មិន​ត្រឹម​ត្រូវ, មិន​អនុញ្ញាត '\\', '/', '<', '>', ':', '\"', '|', '?' និង '*' ទេ។", "Files" => "ឯកសារ", +"Upload cancelled." => "បាន​បោះបង់​ការ​ផ្ទុក​ឡើង។", +"{new_name} already exists" => "មាន​ឈ្មោះ {new_name} រួច​ហើយ", "Share" => "ចែក​រំលែក", +"Delete permanently" => "លុប​ជា​អចិន្ត្រៃយ៍", +"Rename" => "ប្ដូរ​ឈ្មោះ", +"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(""), +"Maximum upload size" => "ទំហំ​ផ្ទុកឡើង​ជា​អតិបរមា", +"Enable ZIP-download" => "បើក​ការ​ទាញយក​ជា ZIP", +"0 is unlimited" => "0 គឺ​មិន​កំណត់", +"Maximum input size for ZIP files" => "ទំហំ​ចូល​ជា​អតិបរមា​សម្រាប់​ឯកសារ ZIP", "Save" => "រក្សាទុក", +"WebDAV" => "WebDAV", +"New" => "ថ្មី", +"Text file" => "ឯកសារ​អក្សរ", "New folder" => "ថត​ថ្មី", "Folder" => "ថត", +"From link" => "ពី​តំណ", +"Cancel upload" => "បោះបង់​ការ​ផ្ទុកឡើង", +"Nothing in here. Upload something!" => "គ្មាន​អ្វី​នៅ​ទីនេះ​ទេ។ ផ្ទុក​ឡើង​អ្វី​មួយ!", "Download" => "ទាញយក", -"Delete" => "លុប" +"Delete" => "លុប", +"Upload too large" => "ផ្ទុក​ឡើង​ធំ​ពេក" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files/l10n/ko.php b/apps/files/l10n/ko.php index bfb69bb444..ae885bb7a3 100644 --- a/apps/files/l10n/ko.php +++ b/apps/files/l10n/ko.php @@ -65,13 +65,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0은 무제한입니다", "Maximum input size for ZIP files" => "ZIP 파일 최대 크기", "Save" => "저장", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "WebDAV로 파일에 접근하려면 이 주소를 사용하십시오", "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!" => "내용이 없습니다. 업로드할 수 있습니다!", diff --git a/apps/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php index b2055162d9..f6fa6514c5 100644 --- a/apps/files/l10n/lt_LT.php +++ b/apps/files/l10n/lt_LT.php @@ -65,13 +65,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 yra neribotas", "Maximum input size for ZIP files" => "Maksimalus ZIP archyvo failo dydis", "Save" => "Išsaugoti", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Naudokite šį adresą, kad pasiektumėte savo failus per WebDAV", "New" => "Naujas", "New text file" => "Naujas tekstinis failas", "Text file" => "Teksto failas", "New folder" => "Naujas aplankas", "Folder" => "Katalogas", "From link" => "Iš nuorodos", -"Deleted files" => "Ištrinti failai", "Cancel upload" => "Atšaukti siuntimą", "You don’t have permission to upload or create files here" => "Jūs neturite leidimo čia įkelti arba kurti failus", "Nothing in here. Upload something!" => "Čia tuščia. Įkelkite ką nors!", diff --git a/apps/files/l10n/lv.php b/apps/files/l10n/lv.php index c5a9b9338a..970e960384 100644 --- a/apps/files/l10n/lv.php +++ b/apps/files/l10n/lv.php @@ -44,12 +44,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 ir neierobežots", "Maximum input size for ZIP files" => "Maksimālais ievades izmērs ZIP datnēm", "Save" => "Saglabāt", +"WebDAV" => "WebDAV", "New" => "Jauna", "Text file" => "Teksta datne", "New folder" => "Jauna mape", "Folder" => "Mape", "From link" => "No saites", -"Deleted files" => "Dzēstās datnes", "Cancel upload" => "Atcelt augšupielādi", "Nothing in here. Upload something!" => "Te vēl nekas nav. Rīkojies, sāc augšupielādēt!", "Download" => "Lejupielādēt", diff --git a/apps/files/l10n/mk.php b/apps/files/l10n/mk.php index 4a1f16c792..293756282c 100644 --- a/apps/files/l10n/mk.php +++ b/apps/files/l10n/mk.php @@ -56,11 +56,11 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 е неограничено", "Maximum input size for ZIP files" => "Максимална големина за внес на ZIP датотеки", "Save" => "Сними", +"WebDAV" => "WebDAV", "New" => "Ново", "Text file" => "Текстуална датотека", "Folder" => "Папка", "From link" => "Од врска", -"Deleted files" => "Избришани датотеки", "Cancel upload" => "Откажи прикачување", "Nothing in here. Upload something!" => "Тука нема ништо. Снимете нешто!", "Download" => "Преземи", diff --git a/apps/files/l10n/nb_NO.php b/apps/files/l10n/nb_NO.php index 80b706dd53..81f96a81c4 100644 --- a/apps/files/l10n/nb_NO.php +++ b/apps/files/l10n/nb_NO.php @@ -65,13 +65,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 er ubegrenset", "Maximum input size for ZIP files" => "Maksimal størrelse på ZIP-filer", "Save" => "Lagre", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Bruk denne adressen for å aksessere filene dine via WebDAV", "New" => "Ny", "New text file" => "Ny tekstfil", "Text file" => "Tekstfil", "New folder" => "Ny mappe", "Folder" => "Mappe", "From link" => "Fra link", -"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!", diff --git a/apps/files/l10n/nl.php b/apps/files/l10n/nl.php index 6bde1e612d..b4b6be8730 100644 --- a/apps/files/l10n/nl.php +++ b/apps/files/l10n/nl.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 is ongelimiteerd", "Maximum input size for ZIP files" => "Maximale grootte voor ZIP bestanden", "Save" => "Bewaren", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Gebruik deze link om uw bestanden via WebDAV te benaderen", "New" => "Nieuw", "New text file" => "Nieuw tekstbestand", "Text file" => "Tekstbestand", "New folder" => "Nieuwe map", "Folder" => "Map", "From link" => "Vanaf link", -"Deleted files" => "Verwijderde bestanden", "Cancel upload" => "Upload afbreken", "You don’t have permission to upload or create files here" => "U hebt geen toestemming om hier te uploaden of bestanden te maken", "Nothing in here. Upload something!" => "Er bevindt zich hier niets. Upload een bestand!", diff --git a/apps/files/l10n/nn_NO.php b/apps/files/l10n/nn_NO.php index 238d1459b1..2c6c0479eb 100644 --- a/apps/files/l10n/nn_NO.php +++ b/apps/files/l10n/nn_NO.php @@ -50,12 +50,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 er ubegrensa", "Maximum input size for ZIP files" => "Maksimal storleik for ZIP-filer", "Save" => "Lagre", +"WebDAV" => "WebDAV", "New" => "Ny", "Text file" => "Tekst fil", "New folder" => "Ny mappe", "Folder" => "Mappe", "From link" => "Frå lenkje", -"Deleted files" => "Sletta filer", "Cancel upload" => "Avbryt opplasting", "Nothing in here. Upload something!" => "Ingenting her. Last noko opp!", "Download" => "Last ned", diff --git a/apps/files/l10n/pl.php b/apps/files/l10n/pl.php index fa9c791144..177ae51391 100644 --- a/apps/files/l10n/pl.php +++ b/apps/files/l10n/pl.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 - bez limitów", "Maximum input size for ZIP files" => "Maksymalna wielkość pliku wejściowego ZIP ", "Save" => "Zapisz", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Użyj tego adresu do dostępu do twoich plików przez WebDAV", "New" => "Nowy", "New text file" => "Nowy plik tekstowy", "Text file" => "Plik tekstowy", "New folder" => "Nowy folder", "Folder" => "Folder", "From link" => "Z odnośnika", -"Deleted files" => "Pliki usunięte", "Cancel upload" => "Anuluj wysyłanie", "You don’t have permission to upload or create files here" => "Nie masz uprawnień do wczytywania lub tworzenia plików w tym miejscu", "Nothing in here. Upload something!" => "Pusto. Wyślij coś!", diff --git a/apps/files/l10n/pt_BR.php b/apps/files/l10n/pt_BR.php index 5e0399bc4e..e65504ea47 100644 --- a/apps/files/l10n/pt_BR.php +++ b/apps/files/l10n/pt_BR.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "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", +"All files" => "Todos os 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", "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}", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 para ilimitado", "Maximum input size for ZIP files" => "Tamanho máximo para arquivo ZIP", "Save" => "Guardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Use este endereço para ter acesso a seus Arquivos via WebDAV", "New" => "Novo", "New text file" => "Novo arquivo texto", "Text file" => "Arquivo texto", "New folder" => "Nova pasta", "Folder" => "Pasta", "From link" => "Do link", -"Deleted files" => "Arquivos apagados", "Cancel upload" => "Cancelar upload", "You don’t have permission to upload or create files here" => "Você não tem permissão para carregar ou criar arquivos aqui", "Nothing in here. Upload something!" => "Nada aqui.Carrege alguma coisa!", diff --git a/apps/files/l10n/pt_PT.php b/apps/files/l10n/pt_PT.php index c6d2767fb8..189cdebf79 100644 --- a/apps/files/l10n/pt_PT.php +++ b/apps/files/l10n/pt_PT.php @@ -3,7 +3,9 @@ $TRANSLATIONS = array( "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.", +"\"%s\" is an invalid file name." => "\"%s\" é um nome de ficheiro inválido.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome Inválido, os caracteres '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", +"The target folder has been moved or deleted." => "A pasta de destino foi movida ou eliminada.", "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", @@ -27,6 +29,8 @@ $TRANSLATIONS = array( "Invalid directory." => "Directório Inválido", "Files" => "Ficheiros", "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", +"Total file size {size1} exceeds upload limit {size2}" => "O tamanho total do ficheiro {size1} excede o limite de carregamento {size2}", +"Not enough free space, you are uploading {size1} but only {size2} is left" => "Não existe espaço suficiente. Está a enviar {size1} mas apenas existe {size2} disponível", "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.", @@ -40,6 +44,7 @@ $TRANSLATIONS = array( "Rename" => "Renomear", "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 a mover o ficheiro.", "Error moving file" => "Erro ao mover o ficheiro", "Error" => "Erro", "Could not rename file" => "Não pôde renomear o ficheiro", @@ -50,6 +55,7 @@ $TRANSLATIONS = array( "_%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"), +"\"{name}\" is an invalid file name." => "\"{name}\" é um nome de ficheiro inválido.", "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", @@ -57,6 +63,7 @@ $TRANSLATIONS = array( "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 (max. %s)" => "Enviar (max. %s)", "File handling" => "Manuseamento de ficheiros", "Maximum upload size" => "Tamanho máximo de envio", "max. possible: " => "max. possivel: ", @@ -65,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 é ilimitado", "Maximum input size for ZIP files" => "Tamanho máximo para ficheiros ZIP", "Save" => "Guardar", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Utilize esta ligação para aceder aos seus ficheiros via WebDAV", "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!", diff --git a/apps/files/l10n/ro.php b/apps/files/l10n/ro.php index c36ba11fc0..befb4bad3a 100644 --- a/apps/files/l10n/ro.php +++ b/apps/files/l10n/ro.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 este nelimitat", "Maximum input size for ZIP files" => "Dimensiunea maximă de intrare pentru fișierele ZIP", "Save" => "Salvează", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Folosește această adresă pentru acces la fișierele tale folosind WebDAV", "New" => "Nou", "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" => "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!", diff --git a/apps/files/l10n/ru.php b/apps/files/l10n/ru.php index 181e063e60..9ebd626eac 100644 --- a/apps/files/l10n/ru.php +++ b/apps/files/l10n/ru.php @@ -71,13 +71,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 - без ограничений", "Maximum input size for ZIP files" => "Максимальный исходный размер для ZIP файлов", "Save" => "Сохранить", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Используйте этот адресс для доступа к вашим файлам через WebDAV", "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!" => "Здесь ничего нет. Загрузите что-нибудь!", diff --git a/apps/files/l10n/sk_SK.php b/apps/files/l10n/sk_SK.php index 66f1c616e4..2372a34aa3 100644 --- a/apps/files/l10n/sk_SK.php +++ b/apps/files/l10n/sk_SK.php @@ -71,13 +71,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 znamená neobmedzené", "Maximum input size for ZIP files" => "Najväčšia veľkosť ZIP súborov", "Save" => "Uložiť", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Použite túto linku pre prístup k vašim súborom cez WebDAV", "New" => "Nový", "New text file" => "Nový textový súbor", "Text file" => "Textový súbor", "New folder" => "Nový priečinok", "Folder" => "Priečinok", "From link" => "Z odkazu", -"Deleted files" => "Zmazané súbory", "Cancel upload" => "Zrušiť odosielanie", "You don’t have permission to upload or create files here" => "Nemáte oprávnenie sem nahrávať alebo vytvoriť súbory", "Nothing in here. Upload something!" => "Žiadny súbor. Nahrajte niečo!", diff --git a/apps/files/l10n/sl.php b/apps/files/l10n/sl.php index b312b2db0d..48f455cc87 100644 --- a/apps/files/l10n/sl.php +++ b/apps/files/l10n/sl.php @@ -44,6 +44,7 @@ $TRANSLATIONS = array( "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", @@ -71,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 predstavlja neomejeno vrednost", "Maximum input size for ZIP files" => "Največja vhodna velikost za datoteke ZIP", "Save" => "Shrani", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Uporabite naslov za dostop do datotek rpeko sistema WebDAV.", "New" => "Novo", "New text file" => "Nova besedilna datoteka", "Text file" => "Besedilna datoteka", "New folder" => "Nova mapa", "Folder" => "Mapa", "From link" => "Iz povezave", -"Deleted files" => "Izbrisane datoteke", "Cancel upload" => "Prekliči pošiljanje", "You don’t have permission to upload or create files here" => "Ni ustreznih dovoljenj za pošiljanje ali ustvarjanje datotek na tem mestu.", "Nothing in here. Upload something!" => "Tukaj še ni ničesar. Najprej je treba kakšno datoteko poslati v oblak!", diff --git a/apps/files/l10n/sq.php b/apps/files/l10n/sq.php index d246fdd6d6..5a125683b0 100644 --- a/apps/files/l10n/sq.php +++ b/apps/files/l10n/sq.php @@ -48,12 +48,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "o është pa limit", "Maximum input size for ZIP files" => "Maksimumi hyrës i skedarëve ZIP", "Save" => "Ruaj", +"WebDAV" => "WebDAV", "New" => "E re", "Text file" => "Skedar tekst", "New folder" => "Dosje e're", "Folder" => "Dosje", "From link" => "Nga lidhja", -"Deleted files" => "Skedarë të fshirë ", "Cancel upload" => "Anullo ngarkimin", "Nothing in here. Upload something!" => "Këtu nuk ka asgje. Ngarko dicka", "Download" => "Shkarko", diff --git a/apps/files/l10n/sr.php b/apps/files/l10n/sr.php index 4cb50b318c..1f0aaab8cf 100644 --- a/apps/files/l10n/sr.php +++ b/apps/files/l10n/sr.php @@ -40,11 +40,11 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 је неограничено", "Maximum input size for ZIP files" => "Највећа величина ZIP датотека", "Save" => "Сачувај", +"WebDAV" => "WebDAV", "New" => "Нова", "Text file" => "текстуална датотека", "Folder" => "фасцикла", "From link" => "Са везе", -"Deleted files" => "Обрисане датотеке", "Cancel upload" => "Прекини отпремање", "Nothing in here. Upload something!" => "Овде нема ничег. Отпремите нешто!", "Download" => "Преузми", diff --git a/apps/files/l10n/sv.php b/apps/files/l10n/sv.php index 8908be66d3..657eef4756 100644 --- a/apps/files/l10n/sv.php +++ b/apps/files/l10n/sv.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "Upload failed. Could not get file info." => "Uppladdning misslyckades. Gick inte att hämta filinformation.", "Invalid directory." => "Felaktig mapp.", "Files" => "Filer", +"All files" => "Alla filer", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Kan inte ladda upp {filename} eftersom den antingen är en mapp eller har 0 bytes.", "Total file size {size1} exceeds upload limit {size2}" => "Totala filstorleken {size1} överskrider uppladdningsgränsen {size2}", "Not enough free space, you are uploading {size1} but only {size2} is left" => "Inte tillräckligt med ledigt utrymme, du laddar upp {size1} men endast {size2} finns kvar.", @@ -44,6 +45,7 @@ $TRANSLATIONS = array( "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 vid flytt av fil.", "Error moving file" => "Fel uppstod vid flyttning av fil", "Error" => "Fel", "Could not rename file" => "Kan ej byta filnamn", @@ -71,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 är oändligt", "Maximum input size for ZIP files" => "Största tillåtna storlek för ZIP-filer", "Save" => "Spara", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Använd denna adress till nå dina Filer via WebDAV", "New" => "Ny", "New text file" => "Ny textfil", "Text file" => "Textfil", "New folder" => "Ny mapp", "Folder" => "Mapp", "From link" => "Från länk", -"Deleted files" => "Raderade filer", "Cancel upload" => "Avbryt uppladdning", "You don’t have permission to upload or create files here" => "Du har ej tillåtelse att ladda upp eller skapa filer här", "Nothing in here. Upload something!" => "Ingenting här. Ladda upp något!", diff --git a/apps/files/l10n/th_TH.php b/apps/files/l10n/th_TH.php index 6371447110..67ebb99f66 100644 --- a/apps/files/l10n/th_TH.php +++ b/apps/files/l10n/th_TH.php @@ -39,6 +39,7 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 หมายถึงไม่จำกัด", "Maximum input size for ZIP files" => "ขนาดไฟล์ ZIP สูงสุด", "Save" => "บันทึก", +"WebDAV" => "WebDAV", "New" => "อัพโหลดไฟล์ใหม่", "Text file" => "ไฟล์ข้อความ", "New folder" => "โฟลเดอร์ใหม่", diff --git a/apps/files/l10n/tr.php b/apps/files/l10n/tr.php index a62e0f3eb6..45e8062ad6 100644 --- a/apps/files/l10n/tr.php +++ b/apps/files/l10n/tr.php @@ -28,6 +28,7 @@ $TRANSLATIONS = array( "Upload failed. Could not get file info." => "Yükleme başarısız. Dosya bilgisi alınamadı.", "Invalid directory." => "Geçersiz dizin.", "Files" => "Dosyalar", +"All files" => "Tüm dosyalar", "Unable to upload {filename} as it is a directory or has 0 bytes" => "Bir dizin veya 0 bayt olduğundan {filename} yüklenemedi", "Total file size {size1} exceeds upload limit {size2}" => "Toplam dosya boyutu {size1}, {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", @@ -72,13 +73,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 limitsiz demektir", "Maximum input size for ZIP files" => "ZIP dosyaları için en fazla girdi boyutu", "Save" => "Kaydet", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "Dosyalarınıza WebDAV aracılığıyla erişmek için bu adresi kullanın", "New" => "Yeni", "New text file" => "Yeni metin dosyası", "Text file" => "Metin dosyası", "New folder" => "Yeni klasör", "Folder" => "Klasör", "From link" => "Bağlantıdan", -"Deleted files" => "Silinmiş dosyalar", "Cancel upload" => "Yüklemeyi iptal et", "You don’t have permission to upload or create files here" => "Buraya dosya yükleme veya oluşturma izniniz yok", "Nothing in here. Upload something!" => "Burada hiçbir şey yok. Bir şeyler yükleyin!", diff --git a/apps/files/l10n/ug.php b/apps/files/l10n/ug.php index 446852368f..b104f60794 100644 --- a/apps/files/l10n/ug.php +++ b/apps/files/l10n/ug.php @@ -22,11 +22,11 @@ $TRANSLATIONS = array( "_%n file_::_%n files_" => array(""), "_Uploading %n file_::_Uploading %n files_" => array(""), "Save" => "ساقلا", +"WebDAV" => "WebDAV", "New" => "يېڭى", "Text file" => "تېكىست ھۆججەت", "New folder" => "يېڭى قىسقۇچ", "Folder" => "قىسقۇچ", -"Deleted files" => "ئۆچۈرۈلگەن ھۆججەتلەر", "Cancel upload" => "يۈكلەشتىن ۋاز كەچ", "Nothing in here. Upload something!" => "بۇ جايدا ھېچنېمە يوق. Upload something!", "Download" => "چۈشۈر", diff --git a/apps/files/l10n/uk.php b/apps/files/l10n/uk.php index 8fb578016c..efdbcc2c4b 100644 --- a/apps/files/l10n/uk.php +++ b/apps/files/l10n/uk.php @@ -48,12 +48,12 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 є безліміт", "Maximum input size for ZIP files" => "Максимальний розмір завантажуємого ZIP файлу", "Save" => "Зберегти", +"WebDAV" => "WebDAV", "New" => "Створити", "Text file" => "Текстовий файл", "New folder" => "Нова тека", "Folder" => "Тека", "From link" => "З посилання", -"Deleted files" => "Видалено файлів", "Cancel upload" => "Перервати завантаження", "Nothing in here. Upload something!" => "Тут нічого немає. Відвантажте що-небудь!", "Download" => "Завантажити", diff --git a/apps/files/l10n/ur_PK.php b/apps/files/l10n/ur_PK.php index b9548acde9..203f93b5e8 100644 --- a/apps/files/l10n/ur_PK.php +++ b/apps/files/l10n/ur_PK.php @@ -1,8 +1,12 @@ "تقسیم", "Error" => "ایرر", +"Name" => "اسم", "_%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" => "حفظ", +"Delete" => "حذف کریں" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files/l10n/vi.php b/apps/files/l10n/vi.php index c14f1b7ea0..c8b8a69604 100644 --- a/apps/files/l10n/vi.php +++ b/apps/files/l10n/vi.php @@ -63,13 +63,13 @@ $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", +"WebDAV" => "WebDAV", "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ì đó !", diff --git a/apps/files/l10n/zh_CN.php b/apps/files/l10n/zh_CN.php index 7f0183e920..39c7f86ece 100644 --- a/apps/files/l10n/zh_CN.php +++ b/apps/files/l10n/zh_CN.php @@ -72,13 +72,14 @@ $TRANSLATIONS = array( "0 is unlimited" => "0 为无限制", "Maximum input size for ZIP files" => "ZIP 文件的最大输入大小", "Save" => "保存", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "使用这个地址 通过 WebDAV 访问您的文件", "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!" => "这里还什么都没有。上传些东西吧!", diff --git a/apps/files/l10n/zh_TW.php b/apps/files/l10n/zh_TW.php index 7b4caf592a..9e56c853ad 100644 --- a/apps/files/l10n/zh_TW.php +++ b/apps/files/l10n/zh_TW.php @@ -62,12 +62,13 @@ $TRANSLATIONS = array( "0 is unlimited" => "0代表沒有限制", "Maximum input size for ZIP files" => "ZIP 壓縮前的原始大小限制", "Save" => "儲存", +"WebDAV" => "WebDAV", +"Use this address to access your Files via WebDAV" => "使用這個地址來透過 WebDAV 存取檔案", "New" => "新增", "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!" => "這裡還沒有東西,上傳一些吧!", diff --git a/apps/files/lib/app.php b/apps/files/lib/app.php index ed4aa32c66..e32225d068 100644 --- a/apps/files/lib/app.php +++ b/apps/files/lib/app.php @@ -30,6 +30,11 @@ class App { */ private $l10n; + /** + * @var \OCP\INavigationManager + */ + private static $navigationManager; + /** * @var \OC\Files\View */ @@ -40,6 +45,18 @@ class App { $this->l10n = $l10n; } + /** + * Returns the app's navigation manager + * + * @return \OCP\INavigationManager + */ + public static function getNavigationManager() { + if (self::$navigationManager === null) { + self::$navigationManager = new \OC\NavigationManager(); + } + return self::$navigationManager; + } + /** * rename a file * diff --git a/apps/files/lib/helper.php b/apps/files/lib/helper.php index 0ae87d12fb..7d8906e225 100644 --- a/apps/files/lib/helper.php +++ b/apps/files/lib/helper.php @@ -1,7 +1,16 @@ + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ namespace OCA\Files; +/** + * Helper class for manipulating file information + */ class Helper { public static function buildFileStorageStatistics($dir) { @@ -9,12 +18,12 @@ class Helper $storageInfo = \OC_Helper::getStorageInfo($dir); $l = new \OC_L10N('files'); - $maxUploadFilesize = \OCP\Util::maxUploadFilesize($dir, $storageInfo['free']); - $maxHumanFilesize = \OCP\Util::humanFileSize($maxUploadFilesize); - $maxHumanFilesize = $l->t('Upload (max. %s)', array($maxHumanFilesize)); + $maxUploadFileSize = \OCP\Util::maxUploadFilesize($dir, $storageInfo['free']); + $maxHumanFileSize = \OCP\Util::humanFileSize($maxUploadFileSize); + $maxHumanFileSize = $l->t('Upload (max. %s)', array($maxHumanFileSize)); - return array('uploadMaxFilesize' => $maxUploadFilesize, - 'maxHumanFilesize' => $maxHumanFilesize, + return array('uploadMaxFilesize' => $maxUploadFileSize, + 'maxHumanFilesize' => $maxHumanFileSize, 'freeSpace' => $storageInfo['free'], 'usedSpacePercent' => (int)$storageInfo['relative']); } @@ -27,20 +36,11 @@ class Helper */ public static function determineIcon($file) { if($file['type'] === 'dir') { - $dir = $file['directory']; $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') { - $icon = \OC_Helper::mimetypeIcon('dir-shared'); - } elseif ($sid[0] !== 'local' and $sid[0] !== 'home') { - $icon = \OC_Helper::mimetypeIcon('dir-external'); - } - } + if ($file->isShared()) { + $icon = \OC_Helper::mimetypeIcon('dir-shared'); + } elseif ($file->isMounted()) { + $icon = \OC_Helper::mimetypeIcon('dir-external'); } }else{ $icon = \OC_Helper::mimetypeIcon($file->getMimetype()); @@ -57,7 +57,7 @@ class Helper * @param \OCP\Files\FileInfo $b file * @return int -1 if $a must come before $b, 1 otherwise */ - public static function fileCmp($a, $b) { + public static function compareFileNames($a, $b) { $aType = $a->getType(); $bType = $b->getType(); if ($aType === 'dir' and $bType !== 'dir') { @@ -69,6 +69,32 @@ class Helper } } + /** + * Comparator function to sort files by date + * + * @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 compareTimestamp($a, $b) { + $aTime = $a->getMTime(); + $bTime = $b->getMTime(); + return $aTime - $bTime; + } + + /** + * Comparator function to sort files by size + * + * @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 compareSize($a, $b) { + $aSize = $a->getSize(); + $bSize = $b->getSize(); + return $aSize - $bSize; + } + /** * Formats the file info to be returned as JSON to the client. * @@ -120,12 +146,35 @@ class Helper * returns it as a sorted array of FileInfo. * * @param string $dir path to the directory + * @param string $sortAttribute attribute to sort on + * @param bool $sortDescending true for descending sort, false otherwise * @return \OCP\Files\FileInfo[] files */ - public static function getFiles($dir) { + public static function getFiles($dir, $sortAttribute = 'name', $sortDescending = false) { $content = \OC\Files\Filesystem::getDirectoryContent($dir); - usort($content, array('\OCA\Files\Helper', 'fileCmp')); - return $content; + return self::sortFiles($content, $sortAttribute, $sortDescending); + } + + /** + * Sort the given file info array + * + * @param \OCP\Files\FileInfo[] $files files to sort + * @param string $sortAttribute attribute to sort on + * @param bool $sortDescending true for descending sort, false otherwise + * @return \OCP\Files\FileInfo[] sorted files + */ + public static function sortFiles($files, $sortAttribute = 'name', $sortDescending = false) { + $sortFunc = 'compareFileNames'; + if ($sortAttribute === 'mtime') { + $sortFunc = 'compareTimestamp'; + } else if ($sortAttribute === 'size') { + $sortFunc = 'compareSize'; + } + usort($files, array('\OCA\Files\Helper', $sortFunc)); + if ($sortDescending) { + $files = array_reverse($files); + } + return $files; } } diff --git a/apps/files/list.php b/apps/files/list.php new file mode 100644 index 0000000000..e583839b25 --- /dev/null +++ b/apps/files/list.php @@ -0,0 +1,38 @@ + + * + * 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 . + * + */ + +// Check if we are a user +OCP\User::checkLoggedIn(); + +$config = \OC::$server->getConfig(); +// TODO: move this to the generated config.js +$publicUploadEnabled = $config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'); +$uploadLimit=OCP\Util::uploadLimit(); + +// renders the controls and table headers template +$tmpl = new OCP\Template('files', 'list', ''); +$tmpl->assign('uploadLimit', $uploadLimit); // PHP upload limit +$tmpl->assign('publicUploadEnabled', $publicUploadEnabled); +$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); +$tmpl->printPage(); + diff --git a/apps/files/templates/appnavigation.php b/apps/files/templates/appnavigation.php new file mode 100644 index 0000000000..86436bbe8c --- /dev/null +++ b/apps/files/templates/appnavigation.php @@ -0,0 +1,17 @@ +
+
    + + + +
+
+
+ +
+
+

t('WebDAV'));?>

+
+ t('Use this address to access your Files via WebDAV', array(link_to_docs('user-webdav'))));?> +
+
+
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 42263c880a..8cab4ce220 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -1,117 +1,15 @@ -
- -
- - -
- - - - - - - - - - - - - - - - - -
-
-
-

- t('The files you are trying to upload exceed the maximum size for file uploads on this server.'));?> -

-
-
-

- t('Files are being scanned, please wait.'));?> -

-

- t('Current scanning'));?> -

-
+ +printPage(); ?> +
+ + + +
- diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php new file mode 100644 index 0000000000..8f11f965b2 --- /dev/null +++ b/apps/files/templates/list.php @@ -0,0 +1,107 @@ +
+ +
+ + +
+ + + + + + + + + + + + + + + +
+ + +
+
+

+ t('The files you are trying to upload exceed the maximum size for file uploads on this server.'));?> +

+
+
+

+ t('Files are being scanned, please wait.'));?> +

+

+ t('Current scanning'));?> +

+
diff --git a/apps/files/tests/ajax_rename.php b/apps/files/tests/ajax_rename.php index 74ca1e4495..9928053e50 100644 --- a/apps/files/tests/ajax_rename.php +++ b/apps/files/tests/ajax_rename.php @@ -24,6 +24,16 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase { private static $user; + /** + * @var PHPUnit_Framework_MockObject_MockObject + */ + private $viewMock; + + /** + * @var \OCA\Files\App + */ + private $files; + function setUp() { // mock OC_L10n if (!self::$user) { @@ -56,7 +66,7 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase { } /** - * @brief test rename of file/folder + * test rename of file/folder */ function testRenameFolder() { $dir = '/'; @@ -72,7 +82,7 @@ class Test_OC_Files_App_Rename extends \PHPUnit_Framework_TestCase { ->method('getFileInfo') ->will($this->returnValue(new \OC\Files\FileInfo( '/', - null, + new \OC\Files\Storage\Local(array('datadir' => '/')), '/', array( 'fileid' => 123, diff --git a/apps/files/tests/helper.php b/apps/files/tests/helper.php new file mode 100644 index 0000000000..9b3603cd56 --- /dev/null +++ b/apps/files/tests/helper.php @@ -0,0 +1,98 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +require_once __DIR__ . '/../lib/helper.php'; + +use OCA\Files; + +/** + * Class Test_Files_Helper + */ +class Test_Files_Helper extends \PHPUnit_Framework_TestCase { + + private function makeFileInfo($name, $size, $mtime, $isDir = false) { + return new \OC\Files\FileInfo( + '/', + null, + '/', + array( + 'name' => $name, + 'size' => $size, + 'mtime' => $mtime, + 'type' => $isDir ? 'dir' : 'file', + 'mimetype' => $isDir ? 'httpd/unix-directory' : 'application/octet-stream' + ) + ); + } + + /** + * Returns a file list for testing + */ + private function getTestFileList() { + return array( + self::makeFileInfo('a.txt', 4, 1000), + self::makeFileInfo('q.txt', 5, 150), + self::makeFileInfo('subdir2', 87, 128, true), + self::makeFileInfo('b.txt', 166, 800), + self::makeFileInfo('o.txt', 12, 100), + self::makeFileInfo('subdir', 88, 125, true), + ); + } + + function sortDataProvider() { + return array( + array( + 'name', + false, + array('subdir', 'subdir2', 'a.txt', 'b.txt', 'o.txt', 'q.txt'), + ), + array( + 'name', + true, + array('q.txt', 'o.txt', 'b.txt', 'a.txt', 'subdir2', 'subdir'), + ), + array( + 'size', + false, + array('a.txt', 'q.txt', 'o.txt', 'subdir2', 'subdir', 'b.txt'), + ), + array( + 'size', + true, + array('b.txt', 'subdir', 'subdir2', 'o.txt', 'q.txt', 'a.txt'), + ), + array( + 'mtime', + false, + array('o.txt', 'subdir', 'subdir2', 'q.txt', 'b.txt', 'a.txt'), + ), + array( + 'mtime', + true, + array('a.txt', 'b.txt', 'q.txt', 'subdir2', 'subdir', 'o.txt'), + ), + ); + } + + /** + * @dataProvider sortDataProvider + */ + public function testSortByName($sort, $sortDescending, $expectedOrder) { + $files = self::getTestFileList(); + $files = \OCA\Files\Helper::sortFiles($files, $sort, $sortDescending); + $fileNames = array(); + foreach ($files as $fileInfo) { + $fileNames[] = $fileInfo->getName(); + } + $this->assertEquals( + $expectedOrder, + $fileNames + ); + } + +} diff --git a/apps/files/tests/js/appSpec.js b/apps/files/tests/js/appSpec.js new file mode 100644 index 0000000000..0e9abad698 --- /dev/null +++ b/apps/files/tests/js/appSpec.js @@ -0,0 +1,220 @@ +/** +* 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 . +* +*/ + +describe('OCA.Files.App tests', function() { + var App = OCA.Files.App; + var pushStateStub; + var parseUrlQueryStub; + + beforeEach(function() { + $('#testArea').append( + '
' + + '
' + + '
' + + '
' + + '' + + '' + + '
' + + '
' + + '' + ); + + pushStateStub = sinon.stub(OC.Util.History, 'pushState'); + parseUrlQueryStub = sinon.stub(OC.Util.History, 'parseUrlQuery'); + parseUrlQueryStub.returns({}); + + App.initialize(); + }); + afterEach(function() { + App.navigation = null; + App.fileList = null; + App.files = null; + App.fileActions.clear(); + App.fileActions = null; + + pushStateStub.restore(); + parseUrlQueryStub.restore(); + }); + + describe('initialization', function() { + it('initializes the default file list with the default file actions', function() { + expect(App.fileList).toBeDefined(); + expect(App.fileList.fileActions.actions.all).toBeDefined(); + expect(App.fileList.$el.is('#app-content-files')).toEqual(true); + }); + }); + + describe('URL handling', function() { + it('pushes the state to the URL when current app changed directory', function() { + $('#app-content-files').trigger(new $.Event('changeDirectory', {dir: 'subdir'})); + expect(pushStateStub.calledOnce).toEqual(true); + expect(pushStateStub.getCall(0).args[0].dir).toEqual('subdir'); + expect(pushStateStub.getCall(0).args[0].view).not.toBeDefined(); + + $('li[data-id=other]>a').click(); + pushStateStub.reset(); + + $('#app-content-other').trigger(new $.Event('changeDirectory', {dir: 'subdir'})); + expect(pushStateStub.calledOnce).toEqual(true); + expect(pushStateStub.getCall(0).args[0].dir).toEqual('subdir'); + expect(pushStateStub.getCall(0).args[0].view).toEqual('other'); + }); + describe('onpopstate', function() { + it('sends "urlChanged" event to current app', function() { + var handler = sinon.stub(); + $('#app-content-files').on('urlChanged', handler); + App._onPopState({view: 'files', dir: '/somedir'}); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].view).toEqual('files'); + expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); + }); + it('sends "show" event to current app and sets navigation', function() { + var showHandlerFiles = sinon.stub(); + var showHandlerOther = sinon.stub(); + var hideHandlerFiles = sinon.stub(); + var hideHandlerOther = sinon.stub(); + $('#app-content-files').on('show', showHandlerFiles); + $('#app-content-files').on('hide', hideHandlerFiles); + $('#app-content-other').on('show', showHandlerOther); + $('#app-content-other').on('hide', hideHandlerOther); + App._onPopState({view: 'other', dir: '/somedir'}); + expect(showHandlerFiles.notCalled).toEqual(true); + expect(hideHandlerFiles.calledOnce).toEqual(true); + expect(showHandlerOther.calledOnce).toEqual(true); + expect(hideHandlerOther.notCalled).toEqual(true); + + showHandlerFiles.reset(); + showHandlerOther.reset(); + hideHandlerFiles.reset(); + hideHandlerOther.reset(); + + App._onPopState({view: 'files', dir: '/somedir'}); + expect(showHandlerFiles.calledOnce).toEqual(true); + expect(hideHandlerFiles.notCalled).toEqual(true); + expect(showHandlerOther.notCalled).toEqual(true); + expect(hideHandlerOther.calledOnce).toEqual(true); + + expect(App.navigation.getActiveItem()).toEqual('files'); + expect($('#app-content-files').hasClass('hidden')).toEqual(false); + expect($('#app-content-other').hasClass('hidden')).toEqual(true); + }); + it('does not send "show" or "hide" event to current app when already visible', function() { + var showHandler = sinon.stub(); + var hideHandler = sinon.stub(); + $('#app-content-files').on('show', showHandler); + $('#app-content-files').on('hide', hideHandler); + App._onPopState({view: 'files', dir: '/somedir'}); + expect(showHandler.notCalled).toEqual(true); + expect(hideHandler.notCalled).toEqual(true); + }); + it('state defaults to files app with root dir', function() { + var handler = sinon.stub(); + parseUrlQueryStub.returns({}); + $('#app-content-files').on('urlChanged', handler); + App._onPopState(); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].view).toEqual('files'); + expect(handler.getCall(0).args[0].dir).toEqual('/'); + }); + it('activates files app if invalid view is passed', function() { + App._onPopState({view: 'invalid', dir: '/somedir'}); + + expect(App.navigation.getActiveItem()).toEqual('files'); + expect($('#app-content-files').hasClass('hidden')).toEqual(false); + }); + }); + describe('navigation', function() { + it('switches the navigation item and panel visibility when onpopstate', function() { + App._onPopState({view: 'other', dir: '/somedir'}); + expect(App.navigation.getActiveItem()).toEqual('other'); + expect($('#app-content-files').hasClass('hidden')).toEqual(true); + expect($('#app-content-other').hasClass('hidden')).toEqual(false); + expect($('li[data-id=files]').hasClass('selected')).toEqual(false); + expect($('li[data-id=other]').hasClass('selected')).toEqual(true); + + App._onPopState({view: 'files', dir: '/somedir'}); + + expect(App.navigation.getActiveItem()).toEqual('files'); + expect($('#app-content-files').hasClass('hidden')).toEqual(false); + expect($('#app-content-other').hasClass('hidden')).toEqual(true); + expect($('li[data-id=files]').hasClass('selected')).toEqual(true); + expect($('li[data-id=other]').hasClass('selected')).toEqual(false); + }); + it('clicking on navigation switches the panel visibility', function() { + $('li[data-id=other]>a').click(); + expect(App.navigation.getActiveItem()).toEqual('other'); + expect($('#app-content-files').hasClass('hidden')).toEqual(true); + expect($('#app-content-other').hasClass('hidden')).toEqual(false); + expect($('li[data-id=files]').hasClass('selected')).toEqual(false); + expect($('li[data-id=other]').hasClass('selected')).toEqual(true); + + $('li[data-id=files]>a').click(); + expect(App.navigation.getActiveItem()).toEqual('files'); + expect($('#app-content-files').hasClass('hidden')).toEqual(false); + expect($('#app-content-other').hasClass('hidden')).toEqual(true); + expect($('li[data-id=files]').hasClass('selected')).toEqual(true); + expect($('li[data-id=other]').hasClass('selected')).toEqual(false); + }); + it('clicking on navigation sends "show" and "urlChanged" event', function() { + var handler = sinon.stub(); + var showHandler = sinon.stub(); + $('#app-content-other').on('urlChanged', handler); + $('#app-content-other').on('show', showHandler); + $('li[data-id=other]>a').click(); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].view).toEqual('other'); + expect(handler.getCall(0).args[0].dir).toEqual('/'); + expect(showHandler.calledOnce).toEqual(true); + }); + it('clicking on activate navigation only sends "urlChanged" event', function() { + var handler = sinon.stub(); + var showHandler = sinon.stub(); + $('#app-content-files').on('urlChanged', handler); + $('#app-content-files').on('show', showHandler); + $('li[data-id=files]>a').click(); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].view).toEqual('files'); + expect(handler.getCall(0).args[0].dir).toEqual('/'); + expect(showHandler.notCalled).toEqual(true); + }); + }); + describe('viewer mode', function() { + it('toggles the sidebar when viewer mode is enabled', function() { + $('#app-content-files').trigger( + new $.Event('changeViewerMode', {viewerModeEnabled: true} + )); + expect($('#app-navigation').hasClass('hidden')).toEqual(true); + expect($('.app-files').hasClass('viewer-mode no-sidebar')).toEqual(true); + + $('#app-content-files').trigger( + new $.Event('changeViewerMode', {viewerModeEnabled: false} + )); + + expect($('#app-navigation').hasClass('hidden')).toEqual(false); + expect($('.app-files').hasClass('viewer-mode no-sidebar')).toEqual(false); + }); + }); + }); +}); diff --git a/apps/files/tests/js/breadcrumbSpec.js b/apps/files/tests/js/breadcrumbSpec.js index 1bfe5308a2..e3d9c757a7 100644 --- a/apps/files/tests/js/breadcrumbSpec.js +++ b/apps/files/tests/js/breadcrumbSpec.js @@ -20,7 +20,9 @@ */ /* global BreadCrumb */ -describe('BreadCrumb tests', function() { +describe('OCA.Files.BreadCrumb tests', function() { + var BreadCrumb = OCA.Files.BreadCrumb; + describe('Rendering', function() { var bc; beforeEach(function() { diff --git a/apps/files/tests/js/fileactionsSpec.js b/apps/files/tests/js/fileactionsSpec.js index f5eafba509..9152dbb58c 100644 --- a/apps/files/tests/js/fileactionsSpec.js +++ b/apps/files/tests/js/fileactionsSpec.js @@ -19,35 +19,45 @@ * */ -/* global OC, FileActions, FileList */ -describe('FileActions tests', function() { - var $filesTable; +describe('OCA.Files.FileActions tests', function() { + var $filesTable, fileList; + var FileActions = OCA.Files.FileActions; beforeEach(function() { // init horrible parameters - var $body = $('body'); + var $body = $('#testArea'); $body.append(''); $body.append(''); // dummy files table $filesTable = $body.append('
'); - FileList.files = []; + fileList = new OCA.Files.FileList($('#testArea')); + FileActions.registerDefaultActions(fileList); }); afterEach(function() { + FileActions.clear(); + fileList = undefined; $('#dir, #permissions, #filestable').remove(); }); + it('calling clear() clears file actions', function() { + FileActions.clear(); + expect(FileActions.actions).toEqual({}); + expect(FileActions.defaults).toEqual({}); + expect(FileActions.icons).toEqual({}); + expect(FileActions.currentFile).toBe(null); + }); it('calling display() sets file actions', function() { var fileData = { id: 18, type: 'file', name: 'testName.txt', - mimetype: 'plain/text', + mimetype: 'text/plain', size: '1234', etag: 'a01234c', mtime: '123456' }; // note: FileActions.display() is called implicitly - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); // actions defined after call expect($tr.find('.action.action-download').length).toEqual(1); @@ -61,12 +71,12 @@ describe('FileActions tests', function() { id: 18, type: 'file', name: 'testName.txt', - mimetype: 'plain/text', + mimetype: 'text/plain', size: '1234', etag: 'a01234c', mtime: '123456' }; - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); FileActions.display($tr.find('td.filename'), true); FileActions.display($tr.find('td.filename'), true); @@ -82,12 +92,12 @@ describe('FileActions tests', function() { id: 18, type: 'file', name: 'testName.txt', - mimetype: 'plain/text', + mimetype: 'text/plain', size: '1234', etag: 'a01234c', mtime: '123456' }; - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); FileActions.display($tr.find('td.filename'), true); $tr.find('.action-download').click(); @@ -97,17 +107,17 @@ describe('FileActions tests', function() { redirectStub.restore(); }); it('deletes file when clicking delete', function() { - var deleteStub = sinon.stub(FileList, 'do_delete'); + var deleteStub = sinon.stub(fileList, 'do_delete'); var fileData = { id: 18, type: 'file', name: 'testName.txt', - mimetype: 'plain/text', + mimetype: 'text/plain', size: '1234', etag: 'a01234c', mtime: '123456' }; - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); FileActions.display($tr.find('td.filename'), true); $tr.find('.action.delete').click(); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 7a2b56d559..bfc983c748 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -19,10 +19,9 @@ * */ -/* global OC, FileList */ -describe('FileList tests', function() { - var testFiles, alertStub, notificationStub, - pushStateStub; +describe('OCA.Files.FileList tests', function() { + var testFiles, alertStub, notificationStub, fileList; + var FileActions = OCA.Files.FileActions; /** * Generate test file data @@ -52,21 +51,13 @@ describe('FileList tests', function() { } beforeEach(function() { - // init horrible parameters - var $body = $('body'); - $body.append(''); - $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( + '
' + + // init horrible parameters '' + '' + // dummy controls @@ -75,19 +66,24 @@ describe('FileList tests', function() { '
' + '
' + // dummy table - // TODO: at some point this will be rendered by the FileList class itself! + // TODO: at some point this will be rendered by the fileList class itself! '' + - '' + + '' + - '' + + '' + + '' + + '' + + '' + + '' + '' + '
' + - '
Empty content message
' + '
Empty content message
' + + '' ); testFiles = [{ @@ -120,27 +116,27 @@ describe('FileList tests', function() { etag: '456' }]; - FileList.initialize(); + fileList = new OCA.Files.FileList($('#app-content-files')); + FileActions.clear(); + FileActions.registerDefaultActions(fileList); + fileList.setFileActions(FileActions); }); afterEach(function() { testFiles = undefined; - FileList.initialized = false; - FileList.isEmpty = true; - delete FileList._reloadCall; + fileList = undefined; - $('#dir, #permissions, #filestable').remove(); + FileActions.clear(); notificationStub.restore(); alertStub.restore(); - pushStateStub.restore(); }); describe('Getters', function() { it('Returns the current directory', function() { $('#dir').val('/one/two/three'); - expect(FileList.getCurrentDirectory()).toEqual('/one/two/three'); + expect(fileList.getCurrentDirectory()).toEqual('/one/two/three'); }); it('Returns the directory permissions as int', function() { $('#permissions').val('23'); - expect(FileList.getDirectoryPermissions()).toEqual(23); + expect(fileList.getDirectoryPermissions()).toEqual(23); }); }); describe('Adding files', function() { @@ -158,12 +154,12 @@ describe('FileList tests', function() { id: 18, type: 'file', name: 'testName.txt', - mimetype: 'plain/text', + mimetype: 'text/plain', size: '1234', etag: 'a01234c', mtime: '123456' }; - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); expect($tr).toBeDefined(); expect($tr[0].tagName.toLowerCase()).toEqual('tr'); @@ -173,12 +169,14 @@ describe('FileList tests', function() { 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-mime')).toEqual('text/plain'); 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('a.name').attr('href')) + .toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2Fsubdir&files=testName.txt'); + expect($tr.find('.nametext').text().trim()).toEqual('testName.txt'); expect($tr.find('.filesize').text()).toEqual('1 kB'); - expect(FileList.findFileEl('testName.txt')[0]).toEqual($tr[0]); + 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 = { @@ -190,7 +188,7 @@ describe('FileList tests', function() { etag: 'a01234c', mtime: '123456' }; - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); expect($tr).toBeDefined(); expect($tr[0].tagName.toLowerCase()).toEqual('tr'); @@ -205,7 +203,7 @@ describe('FileList tests', function() { expect($tr.find('.filesize').text()).toEqual('1 kB'); - expect(FileList.findFileEl('testFolder')[0]).toEqual($tr[0]); + expect(fileList.findFileEl('testFolder')[0]).toEqual($tr[0]); }); it('generates file element with default attributes when calling add() with minimal data', function() { var fileData = { @@ -213,8 +211,8 @@ describe('FileList tests', function() { name: 'testFile.txt' }; - clock.tick(123456); - var $tr = FileList.add(fileData); + clock.tick(123456); + var $tr = fileList.add(fileData); expect($tr).toBeDefined(); expect($tr[0].tagName.toLowerCase()).toEqual('tr'); @@ -234,8 +232,8 @@ describe('FileList tests', function() { type: 'dir', name: 'testFolder' }; - clock.tick(123456); - var $tr = FileList.add(fileData); + clock.tick(123456); + var $tr = fileList.add(fileData); expect($tr).toBeDefined(); expect($tr[0].tagName.toLowerCase()).toEqual('tr'); @@ -256,7 +254,7 @@ describe('FileList tests', function() { name: 'testFolder', size: '0' }; - var $tr = FileList.add(fileData); + var $tr = fileList.add(fileData); expect($tr.find('.filesize').text()).toEqual('0 B'); }); it('adds new file to the end of the list', function() { @@ -265,19 +263,19 @@ describe('FileList tests', function() { type: 'file', name: 'ZZZ.txt' }; - FileList.setFiles(testFiles); - $tr = FileList.add(fileData); + 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]); + 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'); + 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; @@ -286,12 +284,12 @@ describe('FileList tests', function() { name: 'P comes after O.txt' }; for (var i = 0; i < testFiles.length; i++) { - FileList.add(testFiles[i]); + fileList.add(testFiles[i]); } - $tr = FileList.add(fileData); + $tr = fileList.add(fileData); // after "One.txt" expect($tr.index()).toEqual(2); - expect(FileList.files[2]).toEqual(fileData); + expect(fileList.files[2]).toEqual(fileData); }); it('inserts new folder at correct position in insert mode', function() { var $tr; @@ -300,11 +298,11 @@ describe('FileList tests', function() { name: 'somedir2 comes after somedir' }; for (var i = 0; i < testFiles.length; i++) { - FileList.add(testFiles[i]); + fileList.add(testFiles[i]); } - $tr = FileList.add(fileData); + $tr = fileList.add(fileData); expect($tr.index()).toEqual(1); - expect(FileList.files[1]).toEqual(fileData); + expect(fileList.files[1]).toEqual(fileData); }); it('inserts new file at the end correctly', function() { var $tr; @@ -313,21 +311,22 @@ describe('FileList tests', function() { name: 'zzz.txt' }; for (var i = 0; i < testFiles.length; i++) { - FileList.add(testFiles[i]); + fileList.add(testFiles[i]); } - $tr = FileList.add(fileData); + $tr = fileList.add(fileData); expect($tr.index()).toEqual(4); - expect(FileList.files[4]).toEqual(fileData); + expect(fileList.files[4]).toEqual(fileData); }); it('removes empty content message and shows summary when adding first file', function() { + var $summary; var fileData = { type: 'file', name: 'first file.txt', size: 12 }; - FileList.setFiles([]); - expect(FileList.isEmpty).toEqual(true); - FileList.add(fileData); + fileList.setFiles([]); + expect(fileList.isEmpty).toEqual(true); + fileList.add(fileData); $summary = $('#filestable .summary'); expect($summary.hasClass('hidden')).toEqual(false); // yes, ugly... @@ -337,19 +336,20 @@ describe('FileList tests', function() { 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); + 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 $summary; var $removedEl; - FileList.setFiles(testFiles); - $removedEl = FileList.remove('One.txt'); + 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); + expect(fileList.files.length).toEqual(3); + expect(fileList.findFileEl('One.txt').length).toEqual(0); $summary = $('#filestable .summary'); expect($summary.hasClass('hidden')).toEqual(false); @@ -357,27 +357,28 @@ describe('FileList tests', function() { 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); + expect(fileList.isEmpty).toEqual(false); }); it('Shows empty content when removing last file', function() { - FileList.setFiles([testFiles[0]]); - FileList.remove('One.txt'); + var $summary; + 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); + 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); + 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']); + fileList.do_delete(['One.txt', 'Two.jpg']); expect(fakeServer.requests.length).toEqual(1); request = fakeServer.requests[0]; @@ -387,7 +388,8 @@ describe('FileList tests', function() { 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); + var $summary; + fileList.setFiles(testFiles); doDelete(); fakeServer.requests[0].respond( @@ -396,10 +398,10 @@ describe('FileList tests', function() { 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); + 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); @@ -407,28 +409,29 @@ describe('FileList tests', function() { 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(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); + 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); + 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.setFiles(testFiles); - FileList.do_delete(); + fileList.do_delete(); - expect(FileList.$fileList.find('tr .progress-icon:not(.delete-icon)').length).toEqual(4); + 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]]); + var $summary; + fileList.setFiles([testFiles[0], testFiles[1]]); doDelete(); fakeServer.requests[0].respond( @@ -437,17 +440,17 @@ describe('FileList tests', function() { JSON.stringify({status: 'success'}) ); - expect(FileList.$fileList.find('tr').length).toEqual(0); + 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(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); + fileList.setFiles(testFiles); doDelete(); fakeServer.requests[0].respond( @@ -457,9 +460,9 @@ describe('FileList tests', function() { ); // 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(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); }); @@ -469,13 +472,15 @@ describe('FileList tests', function() { var $input, request; for (var i = 0; i < testFiles.length; i++) { - FileList.add(testFiles[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(); + fileList.rename('One.txt'); + $input = fileList.$fileList.find('input.filename'); + $input.val('Tu_after_three.txt'); + // trigger submit because triggering blur doesn't work in all browsers + $input.closest('form').trigger('submit'); expect(fakeServer.requests.length).toEqual(1); request = fakeServer.requests[0]; @@ -483,10 +488,10 @@ describe('FileList tests', function() { 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); + 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); + expect(fileList.$fileList.find('input.filename').length).toEqual(0); } it('Inserts renamed file entry at correct position if rename ajax call suceeded', function() { doRename(); @@ -500,9 +505,9 @@ describe('FileList tests', function() { })); // 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(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); }); @@ -517,9 +522,9 @@ describe('FileList tests', function() { })); // 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(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); }); @@ -534,7 +539,7 @@ describe('FileList tests', function() { } })); - $tr = FileList.findFileEl('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! @@ -551,17 +556,17 @@ describe('FileList tests', function() { } })); - $tr = FileList.findFileEl('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); + fileList.setFiles(testFiles); }); it('Moves single file to target folder', function() { var request; - FileList.move('One.txt', '/somedir'); + fileList.move('One.txt', '/somedir'); expect(fakeServer.requests.length).toEqual(1); request = fakeServer.requests[0]; @@ -576,17 +581,17 @@ describe('FileList tests', function() { } })); - expect(FileList.findFileEl('One.txt').length).toEqual(0); + 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(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'); + fileList.move(['One.txt', 'Two.jpg'], '/somedir'); expect(fakeServer.requests.length).toEqual(2); request = fakeServer.requests[0]; @@ -605,11 +610,11 @@ describe('FileList tests', function() { } })); - expect(FileList.findFileEl('One.txt').length).toEqual(0); + 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(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', @@ -619,17 +624,17 @@ describe('FileList tests', function() { } })); - expect(FileList.findFileEl('Two.jpg').length).toEqual(0); + 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(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'); + fileList.move('One.txt', '/somedir'); expect(fakeServer.requests.length).toEqual(1); request = fakeServer.requests[0]; @@ -643,7 +648,7 @@ describe('FileList tests', function() { } })); - expect(FileList.findFileEl('One.txt').length).toEqual(1); + expect(fileList.findFileEl('One.txt').length).toEqual(1); expect(notificationStub.calledOnce).toEqual(true); expect(notificationStub.getCall(0).args[0]).toEqual('Error while moving file'); @@ -651,47 +656,47 @@ describe('FileList tests', function() { }); 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.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); + expect(fileList.files.length).toEqual(4); + expect(fileList.files).toEqual(testFiles); }); it('updates summary using the file sizes', function() { var $summary; - FileList.setFiles(testFiles); + 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); + 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); + 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([]); + 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); + 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([]); + 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); + 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); + 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); + 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'); @@ -700,121 +705,122 @@ describe('FileList tests', function() { name: 'testFile.txt', directory: '/current dir' }; - var $tr = FileList.add(fileData); - expect(FileList.findFileEl('testFile.txt').length).toEqual(1); + 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); + 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); + fileList.$fileList.on('updated', handler); + fileList.setFiles(testFiles); expect(handler.calledOnce).toEqual(true); }); it('does not update summary when removing non-existing files', function() { + var $summary; // single file - FileList.setFiles([testFiles[0]]); + 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'); + 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)); + fileList.setFiles(generateFiles(0, 64)); }); it('renders only the first page', function() { - expect(FileList.files.length).toEqual(65); + 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); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(40); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(60); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(65); - FileList._nextPage(true); + 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({ + 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); + 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({ + 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.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); + 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({ + fileList.add({ id: 2000, type: 'file', name: 'File with index 19b.txt' }); expect($('#fileList tr').length).toEqual(21); - FileList._nextPage(true); + 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); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(40); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(60); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(65); - FileList._nextPage(true); - FileList.add({ + fileList._nextPage(true); + fileList.add({ id: 2000, type: 'file', name: 'File with index 88.txt' }); expect($('#fileList tr').length).toEqual(66); - FileList._nextPage(true); + 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]); + fileList.add(newFiles[i]); } expect($('#fileList tr').length).toEqual(20); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(40); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(60); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(80); - FileList._nextPage(true); + fileList._nextPage(true); expect($('#fileList tr').length).toEqual(81); - FileList._nextPage(true); + 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); + fileList.remove(fileList.files[0].name); } // still makes sure that there are 20 elements visible, if any expect($('#fileList tr').length).toEqual(25); @@ -834,7 +840,7 @@ describe('FileList tests', function() { } beforeEach(function() { - previewLoadStub = sinon.stub(Files, 'lazyLoadPreview'); + previewLoadStub = sinon.stub(OCA.Files.FileList.prototype, 'lazyLoadPreview'); }); afterEach(function() { previewLoadStub.restore(); @@ -844,7 +850,7 @@ describe('FileList tests', function() { type: 'file', name: 'testFile.txt' }; - var $tr = FileList.add(fileData); + 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); @@ -854,7 +860,7 @@ describe('FileList tests', function() { type: 'dir', name: 'test dir' }; - var $tr = FileList.add(fileData); + 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); @@ -865,7 +871,7 @@ describe('FileList tests', function() { name: 'test dir', icon: OC.webroot + '/core/img/filetypes/application-pdf.svg' }; - var $tr = FileList.add(fileData); + 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); @@ -876,12 +882,12 @@ describe('FileList tests', function() { name: 'test dir', isPreviewAvailable: true }; - var $tr = FileList.add(fileData); + 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'); + previewLoadStub.getCall(0).args[0].callback(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() { @@ -890,7 +896,7 @@ describe('FileList tests', function() { name: 'test dir', isPreviewAvailable: false }; - var $tr = FileList.add(fileData); + 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); @@ -898,26 +904,38 @@ describe('FileList tests', function() { }); describe('viewer mode', function() { it('enabling viewer mode hides files table and action buttons', function() { - FileList.setViewerMode(true); + 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); + 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); + fileList.setViewerMode(true); + fileList.setViewerMode(false); expect($('#filestable').hasClass('hidden')).toEqual(false); expect($('.actions').hasClass('hidden')).toEqual(true); expect($('.notCreatable').hasClass('hidden')).toEqual(false); }); + it('toggling viewer mode triggers event', function() { + var handler = sinon.stub(); + fileList.$el.on('changeViewerMode', handler); + fileList.setViewerMode(true); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].viewerModeEnabled).toEqual(true); + + handler.reset(); + fileList.setViewerMode(false); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].viewerModeEnabled).toEqual(false); + }); }); describe('loading file list', function() { beforeEach(function() { @@ -936,22 +954,22 @@ describe('FileList tests', function() { ]); }); it('fetches file list from server and renders it when reload() is called', function() { - FileList.reload(); + 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'}); + expect(OC.parseQueryString(query)).toEqual({'dir': '/subdir', sort: 'name', sortdirection: 'asc'}); fakeServer.respond(); expect($('#fileList tr').length).toEqual(4); - expect(FileList.findFileEl('One.txt').length).toEqual(1); + 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'); + 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'}); + expect(OC.parseQueryString(query)).toEqual({'dir': '/anothersubdir', sort: 'name', sortdirection: 'asc'}); fakeServer.respond(); }); it('switches to root dir when current directory does not exist', function() { @@ -961,14 +979,14 @@ describe('FileList tests', function() { }, '' ]); - FileList.changeDirectory('/unexist'); + fileList.changeDirectory('/unexist'); fakeServer.respond(); - expect(FileList.getCurrentDirectory()).toEqual('/'); + 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'); + 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(); @@ -977,18 +995,23 @@ describe('FileList tests', function() { 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('triggers "changeDirectory" event when changing directory', function() { + var handler = sinon.stub(); + $('#app-content-files').on('changeDirectory', handler); + fileList.changeDirectory('/somedir'); + expect(handler.calledOnce).toEqual(true); + expect(handler.getCall(0).args[0].dir).toEqual('/somedir'); + }); + it('changes the directory when receiving "urlChanged" event', function() { + $('#app-content-files').trigger(new $.Event('urlChanged', {view: 'files', dir: '/somedir'})); + expect(fileList.getCurrentDirectory()).toEqual('/somedir'); }); it('refreshes breadcrumb after update', function() { - var setDirSpy = sinon.spy(FileList.breadcrumb, 'setDirectory'); - FileList.changeDirectory('/anothersubdir'); + 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); + expect(fileList.breadcrumb.setDirectory.calledOnce).toEqual(true); + expect(fileList.breadcrumb.setDirectory.calledWith('/anothersubdir')).toEqual(true); setDirSpy.restore(); }); }); @@ -1009,20 +1032,20 @@ describe('FileList tests', function() { ]); }); it('clicking on root breadcrumb changes directory to root', function() { - FileList.changeDirectory('/subdir/two/three with space/four/five'); + 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(); + 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'); + 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(); + 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'); @@ -1030,9 +1053,9 @@ describe('FileList tests', function() { }); it('dropping files on breadcrumb calls move operation', function() { var request, query, testDir = '/subdir/two/three with space/four/five'; - FileList.changeDirectory(testDir); + fileList.changeDirectory(testDir); fakeServer.respond(); - var $crumb = FileList.breadcrumb.$el.find('.crumb:eq(3)'); + var $crumb = fileList.breadcrumb.$el.find('.crumb:eq(3)'); // no idea what this is but is required by the handler var ui = { helper: { @@ -1045,7 +1068,7 @@ describe('FileList tests', function() { $('') ]); // simulate drop event - FileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui); + 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); @@ -1071,10 +1094,10 @@ describe('FileList tests', function() { }); }); it('dropping files on same dir breadcrumb does nothing', function() { - var request, query, testDir = '/subdir/two/three with space/four/five'; - FileList.changeDirectory(testDir); + var testDir = '/subdir/two/three with space/four/five'; + fileList.changeDirectory(testDir); fakeServer.respond(); - var $crumb = FileList.breadcrumb.$el.find('.crumb:last'); + var $crumb = fileList.breadcrumb.$el.find('.crumb:last'); // no idea what this is but is required by the handler var ui = { helper: { @@ -1087,7 +1110,7 @@ describe('FileList tests', function() { $('') ]); // simulate drop event - FileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui); + fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui); // no extra server request expect(fakeServer.requests.length).toEqual(1); @@ -1095,32 +1118,32 @@ describe('FileList tests', function() { }); describe('Download Url', function() { it('returns correct download URL for single files', function() { - 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'); + 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'); $('#dir').val('/'); - expect(Files.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?dir=%2F&files=some%20file.txt'); + expect(fileList.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(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'); + 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'); }); 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'); + expect(fileList.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); + fileList.setFiles(testFiles); }); it('Selects a file when clicking its checkbox', function() { - var $tr = FileList.findFileEl('One.txt'); + 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 $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); @@ -1138,7 +1161,7 @@ describe('FileList tests', function() { 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']); + expect(_.pluck(fileList.getSelectedFiles(), 'name')).toEqual(['One.txt', 'Three.pdf']); // deselect now e = new $.Event('click'); @@ -1146,11 +1169,11 @@ describe('FileList tests', function() { $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']); + 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 $tr = fileList.findFileEl('One.txt'); + var $tr2 = fileList.findFileEl('Three.pdf'); var e; $tr.find('td.filename input:checkbox').click(); e = new $.Event('click'); @@ -1159,16 +1182,16 @@ describe('FileList tests', function() { 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(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 $tr = fileList.findFileEl('One.txt'); + var $tr2 = fileList.findFileEl('Three.pdf'); var e; $tr2.find('td.filename input:checkbox').click(); e = new $.Event('click'); @@ -1177,104 +1200,104 @@ describe('FileList tests', function() { 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(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); + expect($('.select-all').prop('checked')).toEqual(false); $('#fileList tr td.filename input:checkbox').click(); - expect($('#select_all').prop('checked')).toEqual(true); + 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.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); + 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.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); + expect(_.pluck(fileList.getSelectedFiles(), 'name').length).toEqual(42); - $('#select_all').click(); - expect($('#select_all').prop('checked')).toEqual(false); + $('.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); + 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); + $('.select-all').click(); + expect($('.select-all').prop('checked')).toEqual(true); - var $tr = FileList.findFileEl('One.txt'); + 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); + 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); + $('.select-all').click(); + expect($('.select-all').prop('checked')).toEqual(true); - var $tr = FileList.findFileEl('One.txt'); + 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); + 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); + $('.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); + 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); + 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(); + 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); + 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'); + var $summary = $('#headerName a.name>span:first'); 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(); + 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(); + var $summary = $('#headerName a.name>span:first'); + 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'); + var $checkbox = fileList.findFileEl('One.txt').find('input:checkbox'); expect($actions.hasClass('hidden')).toEqual(true); $checkbox.click(); expect($actions.hasClass('hidden')).toEqual(false); @@ -1282,7 +1305,7 @@ describe('FileList tests', function() { expect($actions.hasClass('hidden')).toEqual(true); }); it('Selection is cleared when switching dirs', function() { - $('#select_all').click(); + $('.select-all').click(); var data = { status: 'success', data: { @@ -1296,31 +1319,43 @@ describe('FileList tests', function() { }, JSON.stringify(data) ]); - FileList.changeDirectory('/'); + fileList.changeDirectory('/'); fakeServer.respond(); - expect($('#select_all').prop('checked')).toEqual(false); - expect(_.pluck(FileList.getSelectedFiles(), 'name')).toEqual([]); + 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(); + fileList.setFiles(generateFiles(0, 41)); + $('.select-all').click(); // unselect one to not have the "allFiles" case - FileList.$fileList.find('tr input:checkbox:first').click(); + fileList.$fileList.find('tr input:checkbox:first').click(); // only 20 files visible, must still return all the selected ones - selectedFiles = _.pluck(FileList.getSelectedFiles(), 'name'); + selectedFiles = _.pluck(fileList.getSelectedFiles(), 'name'); expect(selectedFiles.length).toEqual(41); }); + describe('Selection overlay', function() { + it('show delete action according to directory permissions', function() { + fileList.setFiles(testFiles); + $('#permissions').val(OC.PERMISSION_READ | OC.PERMISSION_DELETE); + $('.select-all').click(); + expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(false); + $('.select-all').click(); + $('#permissions').val(OC.PERMISSION_READ); + $('.select-all').click(); + expect(fileList.$el.find('.delete-selected').hasClass('hidden')).toEqual(true); + }); + }); 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(); + 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(); + var files = fileList.getSelectedFiles(); expect(files.length).toEqual(3); expect(files[0]).toEqual({ id: 1, @@ -1348,8 +1383,8 @@ describe('FileList tests', function() { }); }); it('Removing a file removes it from the selection', function() { - FileList.remove('Three.pdf'); - var files = FileList.getSelectedFiles(); + fileList.remove('Three.pdf'); + var files = fileList.getSelectedFiles(); expect(files.length).toEqual(2); expect(files[0]).toEqual({ id: 1, @@ -1378,7 +1413,7 @@ describe('FileList tests', function() { }); it('Downloads root folder when all selected in root folder', function() { $('#dir').val('/'); - $('#select_all').click(); + $('.select-all').click(); var redirectStub = sinon.stub(OC, 'redirect'); $('.selectedActions .download').click(); expect(redirectStub.calledOnce).toEqual(true); @@ -1386,7 +1421,7 @@ describe('FileList tests', function() { redirectStub.restore(); }); it('Downloads parent folder when all selected in subfolder', function() { - $('#select_all').click(); + $('.select-all').click(); var redirectStub = sinon.stub(OC, 'redirect'); $('.selectedActions .download').click(); expect(redirectStub.calledOnce).toEqual(true); @@ -1408,14 +1443,14 @@ describe('FileList tests', function() { { '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); + 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(); + $('.select-all').click(); $('.selectedActions .delete-selected').click(); expect(fakeServer.requests.length).toEqual(1); request = fakeServer.requests[0]; @@ -1427,9 +1462,154 @@ describe('FileList tests', function() { { 'Content-Type': 'application/json' }, JSON.stringify({status: 'success'}) ); - expect(FileList.isEmpty).toEqual(true); + expect(fileList.isEmpty).toEqual(true); }); }); }); + it('resets the file selection on reload', function() { + fileList.$el.find('.select-all').click(); + fileList.reload(); + expect(fileList.$el.find('.select-all').prop('checked')).toEqual(false); + expect(fileList.getSelectedFiles()).toEqual([]); + }); + }); + describe('Sorting files', function() { + it('Sorts by name by default', function() { + fileList.reload(); + expect(fakeServer.requests.length).toEqual(1); + var url = fakeServer.requests[0].url; + var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1)); + expect(query.sort).toEqual('name'); + expect(query.sortdirection).toEqual('asc'); + }); + it('Reloads file list with a different sort when clicking on column header of unsorted column', function() { + fileList.$el.find('.column-size .columntitle').click(); + expect(fakeServer.requests.length).toEqual(1); + var url = fakeServer.requests[0].url; + var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1)); + expect(query.sort).toEqual('size'); + expect(query.sortdirection).toEqual('asc'); + }); + it('Toggles sort direction when clicking on already sorted column', function() { + fileList.$el.find('.column-name .columntitle').click(); + expect(fakeServer.requests.length).toEqual(1); + var url = fakeServer.requests[0].url; + var query = OC.parseQueryString(url.substr(url.indexOf('?') + 1)); + expect(query.sort).toEqual('name'); + expect(query.sortdirection).toEqual('desc'); + }); + it('Toggles the sort indicator when clicking on a column header', function() { + var ASC_CLASS = fileList.SORT_INDICATOR_ASC_CLASS; + var DESC_CLASS = fileList.SORT_INDICATOR_DESC_CLASS; + fileList.$el.find('.column-size .columntitle').click(); + // moves triangle to size column + expect( + fileList.$el.find('.column-name .sort-indicator').hasClass(ASC_CLASS + ' ' + DESC_CLASS) + ).toEqual(false); + expect( + fileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS) + ).toEqual(true); + + // click again on size column, reverses direction + fileList.$el.find('.column-size .columntitle').click(); + expect( + fileList.$el.find('.column-size .sort-indicator').hasClass(DESC_CLASS) + ).toEqual(true); + + // click again on size column, reverses direction + fileList.$el.find('.column-size .columntitle').click(); + expect( + fileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS) + ).toEqual(true); + + // click on mtime column, moves indicator there + fileList.$el.find('.column-mtime .columntitle').click(); + expect( + fileList.$el.find('.column-size .sort-indicator').hasClass(ASC_CLASS + ' ' + DESC_CLASS) + ).toEqual(false); + expect( + fileList.$el.find('.column-mtime .sort-indicator').hasClass(ASC_CLASS) + ).toEqual(true); + }); + it('Uses correct sort comparator when inserting files', function() { + testFiles.sort(OCA.Files.FileList.Comparators.size); + // this will make it reload the testFiles with the correct sorting + fileList.$el.find('.column-size .columntitle').click(); + expect(fakeServer.requests.length).toEqual(1); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ + status: 'success', + data: { + files: testFiles, + permissions: 31 + } + }) + ); + var newFileData = { + id: 999, + type: 'file', + name: 'new file.txt', + mimetype: 'text/plain', + size: 40001, + etag: '999' + }; + fileList.add(newFileData); + expect(fileList.files.length).toEqual(5); + expect(fileList.$fileList.find('tr').length).toEqual(5); + expect(fileList.findFileEl('One.txt').index()).toEqual(0); + expect(fileList.findFileEl('somedir').index()).toEqual(1); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); + expect(fileList.findFileEl('new file.txt').index()).toEqual(3); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(4); + }); + it('Uses correct reversed sort comparator when inserting files', function() { + testFiles.sort(OCA.Files.FileList.Comparators.size); + testFiles.reverse(); + // this will make it reload the testFiles with the correct sorting + fileList.$el.find('.column-size .columntitle').click(); + expect(fakeServer.requests.length).toEqual(1); + fakeServer.requests[0].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ + status: 'success', + data: { + files: testFiles, + permissions: 31 + } + }) + ); + // reverse sort + fileList.$el.find('.column-size .columntitle').click(); + fakeServer.requests[1].respond( + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ + status: 'success', + data: { + files: testFiles, + permissions: 31 + } + }) + ); + var newFileData = { + id: 999, + type: 'file', + name: 'new file.txt', + mimetype: 'text/plain', + size: 40001, + etag: '999' + }; + fileList.add(newFileData); + expect(fileList.files.length).toEqual(5); + expect(fileList.$fileList.find('tr').length).toEqual(5); + expect(fileList.findFileEl('One.txt').index()).toEqual(4); + expect(fileList.findFileEl('somedir').index()).toEqual(3); + expect(fileList.findFileEl('Two.jpg').index()).toEqual(2); + expect(fileList.findFileEl('new file.txt').index()).toEqual(1); + expect(fileList.findFileEl('Three.pdf').index()).toEqual(0); + }); }); }); diff --git a/apps/files/tests/js/filesSpec.js b/apps/files/tests/js/filesSpec.js index 7f8848619f..4f8d5a2931 100644 --- a/apps/files/tests/js/filesSpec.js +++ b/apps/files/tests/js/filesSpec.js @@ -19,8 +19,9 @@ * */ -/* global OC, Files */ -describe('Files tests', function() { +describe('OCA.Files.Files tests', function() { + var Files = OCA.Files.Files; + describe('File name validation', function() { it('Validates correct file names', function() { var fileNames = [ @@ -83,18 +84,6 @@ 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'); diff --git a/apps/files/tests/js/filesummarySpec.js b/apps/files/tests/js/filesummarySpec.js index c493700de3..5e39dd1d23 100644 --- a/apps/files/tests/js/filesummarySpec.js +++ b/apps/files/tests/js/filesummarySpec.js @@ -20,7 +20,8 @@ */ /* global FileSummary */ -describe('FileSummary tests', function() { +describe('OCA.Files.FileSummary tests', function() { + var FileSummary = OCA.Files.FileSummary; var $container; beforeEach(function() { diff --git a/apps/files/triggerupdate.php b/apps/files/triggerupdate.php index a37b9823ad..3f85da9913 100644 --- a/apps/files/triggerupdate.php +++ b/apps/files/triggerupdate.php @@ -6,7 +6,7 @@ if (OC::$CLI) { if (count($argv) === 2) { $file = $argv[1]; list(, $user) = explode('/', $file); - OCP\JSON::checkUserExists($owner); + OCP\JSON::checkUserExists($user); OC_Util::setupFS($user); $view = new \OC\Files\View(''); /** diff --git a/apps/files_encryption/ajax/adminrecovery.php b/apps/files_encryption/ajax/adminrecovery.php index 61e43acc2c..303ba0e16e 100644 --- a/apps/files_encryption/ajax/adminrecovery.php +++ b/apps/files_encryption/ajax/adminrecovery.php @@ -5,7 +5,7 @@ * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. * - * @brief Script to handle admin settings for encrypted key recovery + * Script to handle admin settings for encrypted key recovery */ use OCA\Encryption; diff --git a/apps/files_encryption/ajax/changeRecoveryPassword.php b/apps/files_encryption/ajax/changeRecoveryPassword.php index 945f054ea8..0cb010d3b5 100644 --- a/apps/files_encryption/ajax/changeRecoveryPassword.php +++ b/apps/files_encryption/ajax/changeRecoveryPassword.php @@ -5,7 +5,7 @@ * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. * - * @brief Script to change recovery key password + * Script to change recovery key password * */ @@ -23,7 +23,7 @@ $oldPassword = $_POST['oldPassword']; $newPassword = $_POST['newPassword']; $view = new \OC\Files\View('/'); -$util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); +$util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \OCP\User::getUser()); $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; diff --git a/apps/files_encryption/ajax/getMigrationStatus.php b/apps/files_encryption/ajax/getMigrationStatus.php index 7c9e0dcc51..adceb94904 100644 --- a/apps/files_encryption/ajax/getMigrationStatus.php +++ b/apps/files_encryption/ajax/getMigrationStatus.php @@ -4,7 +4,7 @@ * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. * - * @brief check migration status + * check migration status */ use OCA\Encryption\Util; @@ -18,7 +18,7 @@ $migrationStatus = Util::MIGRATION_COMPLETED; if ($loginname !== '' && $password !== '') { $username = \OCP\User::checkPassword($loginname, $password); if ($username) { - $util = new Util(new \OC_FilesystemView('/'), $username); + $util = new Util(new \OC\Files\View('/'), $username); $migrationStatus = $util->getMigrationStatus(); } } diff --git a/apps/files_encryption/ajax/updatePrivateKeyPassword.php b/apps/files_encryption/ajax/updatePrivateKeyPassword.php index 29c72952ae..f7d20c486c 100644 --- a/apps/files_encryption/ajax/updatePrivateKeyPassword.php +++ b/apps/files_encryption/ajax/updatePrivateKeyPassword.php @@ -5,7 +5,7 @@ * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. * - * @brief Script to change recovery key password + * Script to change recovery key password * */ diff --git a/apps/files_encryption/ajax/userrecovery.php b/apps/files_encryption/ajax/userrecovery.php index d6c94bde81..0f3b973d69 100644 --- a/apps/files_encryption/ajax/userrecovery.php +++ b/apps/files_encryption/ajax/userrecovery.php @@ -4,7 +4,7 @@ * This file is licensed under the Affero General Public License version 3 or later. * See the COPYING-README file. * - * @brief Script to handle admin settings for encrypted key recovery + * Script to handle admin settings for encrypted key recovery */ use OCA\Encryption; @@ -19,7 +19,7 @@ if ( ) { $userId = \OCP\USER::getUser(); - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $util = new \OCA\Encryption\Util($view, $userId); // Save recovery preference to DB diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 21de421c19..104e8568ca 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -40,7 +40,7 @@ if (!OC_Config::getValue('maintenance', false)) { \OC_Util::setupFS(); } - $view = new OC_FilesystemView('/'); + $view = new OC\Files\View('/'); $sessionReady = OCA\Encryption\Helper::checkRequirements(); if($sessionReady) { diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 5f0494e62c..c1ccb927df 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -36,7 +36,7 @@ class Hooks { private static $deleteFiles = array(); /** - * @brief Startup encryption backend upon user login + * Startup encryption backend upon user login * @note This method should never be called for users using client side encryption */ public static function login($params) { @@ -48,7 +48,7 @@ class Hooks { $l = new \OC_L10N('files_encryption'); - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); // ensure filesystem is loaded if(!\OC\Files\Filesystem::$loaded) { @@ -93,7 +93,7 @@ class Hooks { // If migration not yet done if ($ready) { - $userView = new \OC_FilesystemView('/' . $params['uid']); + $userView = new \OC\Files\View('/' . $params['uid']); // Set legacy encryption key if it exists, to support // depreciated encryption system @@ -136,26 +136,26 @@ class Hooks { } /** - * @brief setup encryption backend upon user created + * setup encryption backend upon user created * @note This method should never be called for users using client side encryption */ public static function postCreateUser($params) { if (\OCP\App::isEnabled('files_encryption')) { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $util = new Util($view, $params['uid']); Helper::setupUser($util, $params['password']); } } /** - * @brief cleanup encryption backend upon user deleted + * cleanup encryption backend upon user deleted * @note This method should never be called for users using client side encryption */ public static function postDeleteUser($params) { if (\OCP\App::isEnabled('files_encryption')) { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); // cleanup public key $publicKey = '/public-keys/' . $params['uid'] . '.public.key'; @@ -171,7 +171,7 @@ class Hooks { } /** - * @brief If the password can't be changed within ownCloud, than update the key password in advance. + * If the password can't be changed within ownCloud, than update the key password in advance. */ public static function preSetPassphrase($params) { if (\OCP\App::isEnabled('files_encryption')) { @@ -182,7 +182,7 @@ class Hooks { } /** - * @brief Change a user's encryption passphrase + * Change a user's encryption passphrase * @param array $params keys: uid, password */ public static function setPassphrase($params) { @@ -196,7 +196,7 @@ class Hooks { // the necessary keys) if (Crypt::mode() === 'server') { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); if ($params['uid'] === \OCP\User::getUser()) { @@ -259,10 +259,10 @@ class Hooks { } /* - * @brief check if files can be encrypted to every user. + * check if files can be encrypted to every user. */ /** - * @param $params + * @param array $params */ public static function preShared($params) { @@ -308,7 +308,7 @@ class Hooks { if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); @@ -350,7 +350,7 @@ class Hooks { if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); $path = \OC\Files\Filesystem::getPath($params['fileSource']); @@ -398,12 +398,12 @@ class Hooks { } /** - * @brief mark file as renamed so that we know the original source after the file was renamed + * mark file as renamed so that we know the original source after the file was renamed * @param array $params with the old path and the new path */ public static function preRename($params) { $user = \OCP\User::getUser(); - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $util = new Util($view, $user); list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']); @@ -421,8 +421,8 @@ class Hooks { } /** - * @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing - * @param array with oldpath and newpath + * after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing + * @param array $params array with oldpath and newpath * * This function is connected to the rename signal of OC_Filesystem and adjust the name and location * of the stored versions along the actual file @@ -437,7 +437,7 @@ class Hooks { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $session = new \OCA\Encryption\Session($view); $userId = \OCP\User::getUser(); $util = new Util($view, $userId); @@ -557,7 +557,7 @@ class Hooks { } /** - * @brief if the file was really deleted we remove the encryption keys + * if the file was really deleted we remove the encryption keys * @param array $params * @return boolean|null */ @@ -597,7 +597,7 @@ class Hooks { } /** - * @brief remember the file which should be deleted and it's owner + * remember the file which should be deleted and it's owner * @param array $params * @return boolean|null */ @@ -610,7 +610,7 @@ class Hooks { return true; } - $util = new Util(new \OC_FilesystemView('/'), \OCP\USER::getUser()); + $util = new Util(new \OC\Files\View('/'), \OCP\USER::getUser()); list($owner, $ownerPath) = $util->getUidAndFilename($path); self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]] = array( diff --git a/apps/files_encryption/l10n/ast.php b/apps/files_encryption/l10n/ast.php index 7e08e07309..8b51ec775d 100644 --- a/apps/files_encryption/l10n/ast.php +++ b/apps/files_encryption/l10n/ast.php @@ -1,13 +1,44 @@ "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", +"Recovery key successfully enabled" => "Habilitóse la recuperación de ficheros", +"Could not enable recovery key. Please check your recovery key password!" => "Nun pudo habilitase la clave de recuperación. Por favor comprueba la contraseña.", +"Recovery key successfully disabled" => "Clave de recuperación deshabilitada", +"Could not disable recovery key. Please check your recovery key password!" => "Nun pudo deshabilitase la clave de recuperación. Por favor comprueba la contraseña!", +"Password successfully changed." => "Camudóse la contraseña", +"Could not change the password. Maybe the old password was not correct." => "Nun pudo camudase la contraseña. Comprueba que la contraseña actual seya correuta.", +"Private key password successfully updated." => "Contraseña de clave privada anovada correchamente.", +"Could not update the private key password. Maybe the old password was not correct." => "Nun pudo camudase la contraseña. Pue que la contraseña antigua nun seya correuta.", +"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." => "¡L'aplicación de cifráu nun s'anició! Seique se restableciera mentanto la sesión. Por favor intenta zarrar la sesión y volver a aniciala p'aniciar l'aplicación de cifráu.", +"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." => "¡La clave privada nun ye válida! Seique la contraseña se camudase dende fuera de %s (Ex:El to direutoriu corporativu). Pues anovar la contraseña de la clave privada nes tos opciones personales pa recuperar l'accesu a los ficheros.", +"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "Nun pudo descifrase esti ficheru, dablemente seya un ficheru compartíu. Solicita al propietariu del mesmu que vuelva a compartilu contigo.", +"Unknown error please check your system settings or contact your administrator" => "Fallu desconocíu. Verifica la configuración del sistema o ponte en contautu col alministrador", +"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úrate de que PHP 5.3.3 o postreru ta instaláu y que la estensión OpenSSL de PHP ta habilitada y configurada correutamente. Pel momentu, l'aplicación de cifráu deshabilitóse.", +"Following users are not set up for encryption:" => "Los siguientes usuarios nun se configuraron pal cifráu:", +"Initial encryption started... This can take some time. Please wait." => "Cifráu aniciáu..... Esto pue llevar un tiempu. Por favor espera.", +"Initial encryption running... Please try again later." => "Cifráu inicial en cursu... Inténtalo dempués.", +"Go directly to your " => "Dir direutamente a", +"personal settings" => "opciones personales", "Encryption" => "Cifráu", -"Enabled" => "Habilitáu", +"Enable recovery key (allow to recover users files in case of password loss):" => "Habilitar la clave de recuperación (permite recuperar los ficheros del usuariu en casu de perda de la contraseña);", +"Recovery key password" => "Contraseña de clave de recuperación", +"Repeat Recovery key password" => "Repeti la contraseña de clave de recuperación", +"Enabled" => "Habilitar", "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" +"Change recovery key password:" => "Camudar la contraseña de la clave de recuperación", +"Old Recovery key password" => "Clave de recuperación vieya", +"New Recovery key password" => "Clave de recuperación nueva", +"Repeat New Recovery key password" => "Repetir la clave de recuperación nueva", +"Change Password" => "Camudar contraseña", +"Your private key password no longer match your log-in password:" => "La to contraseña de clave privada yá nun concasa cola contraseña d'accesu:", +"Set your old private key password to your current log-in password." => "Afitar la contraseña de la to clave privada vieya a la to contraseña actual d'accesu.", +" If you don't remember your old password you can ask your administrator to recover your files." => "Si nun recuerdes la contraseña vieya, pues pidir a alministrador que te recupere los ficheros.", +"Old log-in password" => "Contraseña d'accesu vieya", +"Current log-in password" => "Contraseña d'accesu actual", +"Update Private Key Password" => "Anovar Contraseña de Clave Privada", +"Enable password recovery:" => "Habilitar la recuperación de contraseña:", +"Enabling this option will allow you to reobtain access to your encrypted files in case of password loss" => "Habilitar esta opción va permitite volver a tener accesu a los ficheros cifraos en casu de perda de contraseña", +"File recovery settings updated" => "Opciones de recuperación de ficheros anovada", +"Could not update file recovery" => "Nun pudo anovase la recuperación de ficheros" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_encryption/l10n/fa.php b/apps/files_encryption/l10n/fa.php index 3f8d631e10..420fd7423f 100644 --- a/apps/files_encryption/l10n/fa.php +++ b/apps/files_encryption/l10n/fa.php @@ -9,6 +9,7 @@ $TRANSLATIONS = array( "Private key password successfully updated." => "رمزعبور کلید خصوصی با موفقیت به روز شد.", "Could not update the private key password. Maybe the old password was not correct." => "رمزعبور کلید خصوصی را نمی تواند به روز کند. شاید رمزعبور قدیمی صحیح نمی باشد.", "Missing requirements." => "نیازمندی های گمشده", +"Following users are not set up for encryption:" => "کاربران زیر برای رمزنگاری تنظیم نشده اند", "personal settings" => "تنظیمات شخصی", "Encryption" => "رمزگذاری", "Enable recovery key (allow to recover users files in case of password loss):" => "فعال کردن کلید بازیابی(اجازه بازیابی فایل های کاربران در صورت از دست دادن رمزعبور):", diff --git a/apps/files_encryption/l10n/pt_PT.php b/apps/files_encryption/l10n/pt_PT.php index 9a1963953e..409f1917a4 100644 --- a/apps/files_encryption/l10n/pt_PT.php +++ b/apps/files_encryption/l10n/pt_PT.php @@ -10,17 +10,21 @@ $TRANSLATIONS = array( "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.", +"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 PHP 5.3.3 ou mais recente está instalado e que OpenSSL juntamente com a extensão PHP está ativada e corretamente configurada. Por agora, a aplicação de encriptação está desactivada.", "Following users are not set up for encryption:" => "Os utilizadores seguintes não estão marcados para cifragem:", +"Initial encryption started... This can take some time. Please wait." => "A encriptação inicial começou... Pode demorar algum tempo. Aguarde, por favor.", "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):", "Recovery key password" => "Chave de recuperação da conta", +"Repeat Recovery key password" => "Repetir a chave de recuperação da conta", "Enabled" => "Activado", "Disabled" => "Desactivado", "Change recovery key password:" => "Alterar a chave de recuperação:", "Old Recovery key password" => "Chave anterior de recuperação da conta", "New Recovery key password" => "Nova chave de recuperação da conta", +"Repeat New Recovery key password" => "Repetir a nova chave de recuperação da conta", "Change Password" => "Mudar a Password", "Old log-in password" => "Password anterior da conta", "Current log-in password" => "Password actual da conta", diff --git a/apps/files_encryption/l10n/tr.php b/apps/files_encryption/l10n/tr.php index 85e35f5ddd..ba87330c48 100644 --- a/apps/files_encryption/l10n/tr.php +++ b/apps/files_encryption/l10n/tr.php @@ -9,7 +9,7 @@ $TRANSLATIONS = array( "Private key password successfully updated." => "Gizli anahtar parolası başarıyla güncellendi", "Could not update the private key password. Maybe the old password was not correct." => "Gizli anahtar parolası güncellenemedi. Eski parola hatalı olabilir.", "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." => "Şifreleme uygulaması başlatılamadı! Oturumunuz sırasında şifreleme uygulaması tekrar etkinleştirilmiş olabilir. Lütfen şifreleme uygulamasını başlatmak için oturumu kapatıp yeniden oturum açmayı deneyin.", -"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." => "Gizli anahtarınız geçerli değil! Muhtemelen parolanız ownCloud sistemi %s dışarısında değiştirildi (örn. şirket dizininde). Gizli anahtar parolanızı kişisel ayarlarınızda güncelleyerek şifreli dosyalarınıza erişimi kurtarabilirsiniz.", +"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." => "Gizli anahtarınız geçerli değil! Muhtemelen parolanız %s dışarısında değiştirildi (örn. şirket dizininde). Gizli anahtar parolanızı kişisel ayarlarınızda güncelleyerek şifreli dosyalarınıza erişimi kurtarabilirsiniz.", "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." => "Bu dosya muhtemelen bir paylaşılan dosya olduğundan şifresi çözülemiyor. Lütfen dosyayı sizinle bir daha paylaşması için dosya sahibi ile iletişime geçin.", "Unknown error please check your system settings or contact your administrator" => "Bilinmeyen hata. Lütfen sistem ayarlarınızı denetleyin veya yöneticiniz ile iletişime geçin", "Missing requirements." => "Gereklilikler eksik.", diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index a4f7bd3549..ec7b3bc92e 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -40,7 +40,7 @@ class Crypt { /** - * @brief return encryption mode client or server side encryption + * return encryption mode client or server side encryption * @param string $user name (use system wide setting if name=null) * @return string 'client' or 'server' */ @@ -51,7 +51,7 @@ class Crypt { } /** - * @brief Create a new encryption keypair + * Create a new encryption keypair * @return array publicKey, privatekey */ public static function createKeypair() { @@ -85,7 +85,7 @@ class Crypt { } /** - * @brief Add arbitrary padding to encrypted data + * Add arbitrary padding to encrypted data * @param string $data data to be padded * @return string padded data * @note In order to end up with data exactly 8192 bytes long we must @@ -102,7 +102,7 @@ class Crypt { } /** - * @brief Remove arbitrary padding to encrypted data + * Remove arbitrary padding to encrypted data * @param string $padded padded data to remove padding from * @return string unpadded data on success, false on error */ @@ -124,8 +124,8 @@ class Crypt { } /** - * @brief Check if a file's contents contains an IV and is symmetrically encrypted - * @param $content + * Check if a file's contents contains an IV and is symmetrically encrypted + * @param string $content * @return boolean * @note see also OCA\Encryption\Util->isEncryptedPath() */ @@ -178,11 +178,10 @@ class Crypt { } /** - * @brief Check if a file is encrypted via legacy system - * @param $data + * Check if a file is encrypted via legacy system + * @param boolean $isCatFileContent * @param string $relPath The path of the file, relative to user/data; * e.g. filename or /Docs/filename, NOT admin/files/filename - * @param boolean $isCatFileContent * @return boolean */ public static function isLegacyEncryptedContent($isCatFileContent, $relPath) { @@ -209,7 +208,7 @@ class Crypt { } /** - * @brief Symmetrically encrypt a string + * Symmetrically encrypt a string * @param string $plainContent * @param string $iv * @param string $passphrase @@ -229,7 +228,7 @@ class Crypt { } /** - * @brief Symmetrically decrypt a string + * Symmetrically decrypt a string * @param string $encryptedContent * @param string $iv * @param string $passphrase @@ -251,10 +250,10 @@ class Crypt { } /** - * @brief Concatenate encrypted data with its IV and padding + * Concatenate encrypted data with its IV and padding * @param string $content content to be concatenated * @param string $iv IV to be concatenated - * @returns string concatenated content + * @return string concatenated content */ private static function concatIv($content, $iv) { @@ -265,9 +264,9 @@ class Crypt { } /** - * @brief Split concatenated data and IV into respective parts + * Split concatenated data and IV into respective parts * @param string $catFile concatenated data to be split - * @returns array keys: encrypted, iv + * @return array keys: encrypted, iv */ private static function splitIv($catFile) { @@ -290,7 +289,7 @@ class Crypt { } /** - * @brief Symmetrically encrypts a string and returns keyfile content + * Symmetrically encrypts a string and returns keyfile content * @param string $plainContent content to be encrypted in keyfile * @param string $passphrase * @return false|string encrypted content combined with IV @@ -322,15 +321,15 @@ class Crypt { /** - * @brief Symmetrically decrypts keyfile content - * @param $keyfileContent + * Symmetrically decrypts keyfile content + * @param string $keyfileContent * @param string $passphrase * @throws \Exception * @return string|false * @internal param string $source * @internal param string $target * @internal param string $key the decryption key - * @returns string decrypted content + * @return string decrypted content * * This function decrypts a file */ @@ -359,10 +358,10 @@ class Crypt { } /** - * @brief Decrypt private key and check if the result is a valid keyfile + * Decrypt private key and check if the result is a valid keyfile * @param string $encryptedKey encrypted keyfile * @param string $passphrase to decrypt keyfile - * @returns encrypted private key or false + * @return string|false encrypted private key or false * * This function decrypts a file */ @@ -386,10 +385,10 @@ class Crypt { } /** - * @brief Create asymmetrically encrypted keyfile content using a generated key + * Create asymmetrically encrypted keyfile content using a generated key * @param string $plainContent content to be encrypted * @param array $publicKeys array keys must be the userId of corresponding user - * @returns array keys: keys (array, key = userId), data + * @return array keys: keys (array, key = userId), data * @note symmetricDecryptFileContent() can decrypt files created using this method */ public static function multiKeyEncrypt($plainContent, array $publicKeys) { @@ -434,13 +433,13 @@ class Crypt { } /** - * @brief Asymmetrically encrypt a file using multiple public keys - * @param $encryptedContent - * @param $shareKey - * @param $privateKey + * Asymmetrically encrypt a file using multiple public keys + * @param string $encryptedContent + * @param string $shareKey + * @param mixed $privateKey * @return false|string * @internal param string $plainContent content to be encrypted - * @returns string $plainContent decrypted string + * @return string $plainContent decrypted string * @note symmetricDecryptFileContent() can be used to decrypt files created using this method * * This function decrypts a file @@ -468,7 +467,7 @@ class Crypt { } /** - * @brief Generates a pseudo random initialisation vector + * Generates a pseudo random initialisation vector * @return String $iv generated IV */ private static function generateIv() { @@ -497,8 +496,8 @@ class Crypt { } /** - * @brief Generate a pseudo random 256-bit ASCII key, used as file key - * @returns $key Generated key + * Generate a pseudo random 256-bit ASCII key, used as file key + * @return string|false Generated key */ public static function generateKey() { @@ -523,8 +522,8 @@ class Crypt { } /** - * @brief Get the blowfish encryption handler for a key - * @param $key string (optional) + * Get the blowfish encryption handler for a key + * @param string $key (optional) * @return \Crypt_Blowfish blowfish object * * if the key is left out, the default handler will be used @@ -544,7 +543,7 @@ class Crypt { } /** - * @brief decrypts content using legacy blowfish system + * decrypts content using legacy blowfish system * @param string $content the cleartext message you want to decrypt * @param string $passphrase * @return string cleartext content @@ -561,7 +560,7 @@ class Crypt { } /** - * @param $data + * @param string $data * @param string $key * @param int $maxLength * @return string diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index 8cbbe8a45a..564e97e059 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -24,7 +24,7 @@ namespace OCA\Encryption; /** - * @brief Class to manage registration of hooks an various helper methods + * Class to manage registration of hooks an various helper methods * @package OCA\Encryption */ class Helper { @@ -32,7 +32,7 @@ class Helper { private static $tmpFileMapping; // Map tmp files to files in data/user/files /** - * @brief register share related hooks + * register share related hooks * */ public static function registerShareHooks() { @@ -43,7 +43,7 @@ class Helper { } /** - * @brief register user related hooks + * register user related hooks * */ public static function registerUserHooks() { @@ -56,7 +56,7 @@ class Helper { } /** - * @brief register filesystem related hooks + * register filesystem related hooks * */ public static function registerFilesystemHooks() { @@ -68,7 +68,7 @@ class Helper { } /** - * @brief register app management related hooks + * register app management related hooks * */ public static function registerAppHooks() { @@ -78,7 +78,7 @@ class Helper { } /** - * @brief setup user for files_encryption + * setup user for files_encryption * * @param Util $util * @param string $password @@ -100,9 +100,9 @@ class Helper { } /** - * @brief enable recovery + * enable recovery * - * @param $recoveryKeyId + * @param string $recoveryKeyId * @param string $recoveryPassword * @internal param \OCA\Encryption\Util $util * @internal param string $password @@ -153,7 +153,7 @@ class Helper { $return = true; } else { // get recovery key and check the password - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); + $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \OCP\User::getUser()); $return = $util->checkRecoveryPassword($recoveryPassword); if ($return) { $appConfig->setValue('files_encryption', 'recoveryAdminEnabled', 1); @@ -164,7 +164,7 @@ class Helper { } /** - * @brief Check if a path is a .part file + * Check if a path is a .part file * @param string $path Path that may identify a .part file * @return bool */ @@ -181,7 +181,7 @@ class Helper { /** - * @brief Remove .path extension from a file path + * Remove .path extension from a file path * @param string $path Path that may identify a .part file * @return string File path without .part extension * @note this is needed for reusing keys @@ -208,13 +208,13 @@ class Helper { } /** - * @brief disable recovery + * disable recovery * * @param string $recoveryPassword * @return bool */ public static function adminDisableRecovery($recoveryPassword) { - $util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser()); + $util = new Util(new \OC\Files\View('/'), \OCP\User::getUser()); $return = $util->checkRecoveryPassword($recoveryPassword); if ($return) { @@ -227,7 +227,7 @@ class Helper { /** - * @brief checks if access is public/anonymous user + * checks if access is public/anonymous user * @return bool */ public static function isPublicAccess() { @@ -239,7 +239,7 @@ class Helper { } /** - * @brief Format a path to be relative to the /user/files/ directory + * 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' */ @@ -259,7 +259,7 @@ class Helper { } /** - * @brief try to get the user from the path if no user is logged in + * try to get the user from the path if no user is logged in * @param string $path * @return mixed user or false if we couldn't determine a user */ @@ -294,7 +294,7 @@ class Helper { } /** - * @brief get path to the corresponding file in data/user/files if path points + * get path to the corresponding file in data/user/files if path points * to a version or to a file in cache * @param string $path path to a version or a file in the trash * @return string path to corresponding file relative to data/user/files @@ -327,12 +327,12 @@ class Helper { } /** - * @brief create directory recursively + * create directory recursively * @param string $path * @param \OC\Files\View $view */ public static function mkdirr($path, $view) { - $dirname = \OC_Filesystem::normalizePath(dirname($path)); + $dirname = \OC\Files\Filesystem::normalizePath(dirname($path)); $dirParts = explode('/', $dirname); $dir = ""; foreach ($dirParts as $part) { @@ -344,7 +344,7 @@ class Helper { } /** - * @brief redirect to a error page + * redirect to a error page * @param Session $session */ public static function redirectToErrorPage($session, $errorCode = null) { @@ -428,7 +428,7 @@ class Helper { } /** - * @brief glob uses different pattern than regular expressions, escape glob pattern only + * glob uses different pattern than regular expressions, escape glob pattern only * @param string $path unescaped path * @return string path */ @@ -437,7 +437,7 @@ class Helper { } /** - * @brief remember from which file the tmp file (getLocalFile() call) was created + * remember from which file the tmp file (getLocalFile() call) was created * @param string $tmpFile path of tmp file * @param string $originalFile path of the original file relative to data/ */ @@ -446,7 +446,7 @@ class Helper { } /** - * @brief get the path of the original file + * get the path of the original file * @param string $tmpFile path of the tmp file * @return string|false path of the original file or false */ diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index cb9f5e64af..3c51c5efba 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -24,20 +24,20 @@ namespace OCA\Encryption; /** - * @brief Class to manage storage and retrieval of encryption keys + * Class to manage storage and retrieval of encryption keys * @note Where a method requires a view object, it's root must be '/' */ class Keymanager { /** - * @brief retrieve the ENCRYPTED private key from a user + * retrieve the ENCRYPTED private key from a user * - * @param \OC_FilesystemView $view + * @param \OC\Files\View $view * @param string $user * @return string private key or false (hopefully) * @note the key returned by this method must be decrypted before use */ - public static function getPrivateKey(\OC_FilesystemView $view, $user) { + public static function getPrivateKey(\OC\Files\View $view, $user) { $path = '/' . $user . '/' . 'files_encryption' . '/' . $user . '.private.key'; $key = false; @@ -55,12 +55,12 @@ class Keymanager { } /** - * @brief retrieve public key for a specified user - * @param \OC_FilesystemView $view - * @param $userId + * retrieve public key for a specified user + * @param \OC\Files\View $view + * @param string $userId * @return string public key or false */ - public static function getPublicKey(\OC_FilesystemView $view, $userId) { + public static function getPublicKey(\OC\Files\View $view, $userId) { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -74,12 +74,12 @@ class Keymanager { } /** - * @brief Retrieve a user's public and private key - * @param \OC_FilesystemView $view - * @param $userId + * Retrieve a user's public and private key + * @param \OC\Files\View $view + * @param string $userId * @return array keys: privateKey, publicKey */ - public static function getUserKeys(\OC_FilesystemView $view, $userId) { + public static function getUserKeys(\OC\Files\View $view, $userId) { return array( 'publicKey' => self::getPublicKey($view, $userId), @@ -89,12 +89,12 @@ class Keymanager { } /** - * @brief Retrieve public keys for given users - * @param \OC_FilesystemView $view + * Retrieve public keys for given users + * @param \OC\Files\View $view * @param array $userIds * @return array of public keys for the specified users */ - public static function getPublicKeys(\OC_FilesystemView $view, array $userIds) { + public static function getPublicKeys(\OC\Files\View $view, array $userIds) { $keys = array(); @@ -109,9 +109,9 @@ class Keymanager { } /** - * @brief store file encryption key + * store file encryption key * - * @param \OC_FilesystemView $view + * @param \OC\Files\View $view * @param \OCA\Encryption\Util $util * @param string $path relative path of the file, including filename * @param string $catfile keyfile content @@ -119,7 +119,7 @@ class Keymanager { * @note The keyfile is not encrypted here. Client code must * asymmetrically encrypt the keyfile before passing it to this method */ - public static function setFileKey(\OC_FilesystemView $view, $util, $path, $catfile) { + public static function setFileKey(\OC\Files\View $view, $util, $path, $catfile) { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -167,8 +167,8 @@ class Keymanager { } /** - * @brief retrieve keyfile for an encrypted file - * @param \OC_FilesystemView $view + * retrieve keyfile for an encrypted file + * @param \OC\Files\View $view * @param \OCA\Encryption\Util $util * @param string|false $filePath * @internal param \OCA\Encryption\file $string name @@ -210,9 +210,9 @@ class Keymanager { } /** - * @brief Delete a keyfile + * Delete a keyfile * - * @param \OC_FilesystemView $view + * @param \OC\Files\View $view * @param string $path path of the file the key belongs to * @param string $userId the user to whom the file belongs * @return bool Outcome of unlink operation @@ -266,7 +266,7 @@ class Keymanager { } /** - * @brief store private key from the user + * store private key from the user * @param string $key * @return bool * @note Encryption of the private key must be performed by client code @@ -276,7 +276,7 @@ class Keymanager { $user = \OCP\User::getUser(); - $view = new \OC_FilesystemView('/' . $user . '/files_encryption'); + $view = new \OC\Files\View('/' . $user . '/files_encryption'); $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -293,16 +293,16 @@ class Keymanager { } /** - * @brief store share key + * store share key * - * @param \OC_FilesystemView $view + * @param \OC\Files\View $view * @param string $path where the share key is stored - * @param $shareKey + * @param string $shareKey * @return bool true/false * @note The keyfile is not encrypted here. Client code must * asymmetrically encrypt the keyfile before passing it to this method */ - private static function setShareKey(\OC_FilesystemView $view, $path, $shareKey) { + private static function setShareKey(\OC\Files\View $view, $path, $shareKey) { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -319,14 +319,14 @@ class Keymanager { } /** - * @brief store multiple share keys for a single file - * @param \OC_FilesystemView $view + * store multiple share keys for a single file + * @param \OC\Files\View $view * @param \OCA\Encryption\Util $util * @param string $path * @param array $shareKeys * @return bool */ - public static function setShareKeys(\OC_FilesystemView $view, $util, $path, array $shareKeys) { + public static function setShareKeys(\OC\Files\View $view, $util, $path, array $shareKeys) { // $shareKeys must be an array with the following format: // [userId] => [encrypted key] @@ -365,8 +365,8 @@ class Keymanager { } /** - * @brief retrieve shareKey for an encrypted file - * @param \OC_FilesystemView $view + * retrieve shareKey for an encrypted file + * @param \OC\Files\View $view * @param string $userId * @param \OCA\Encryption\Util $util * @param string $filePath @@ -374,7 +374,7 @@ class Keymanager { * @note The sharekey returned is encrypted. Decryption * of the keyfile must be performed by client code */ - public static function getShareKey(\OC_FilesystemView $view, $userId, $util, $filePath) { + public static function getShareKey(\OC\Files\View $view, $userId, $util, $filePath) { // try reusing key file if part file $proxyStatus = \OC_FileProxy::$enabled; @@ -406,8 +406,8 @@ class Keymanager { } /** - * @brief delete all share keys of a given file - * @param \OC_FilesystemView $view + * delete all share keys of a given file + * @param \OC\Files\View $view * @param string $userId owner of the file * @param string $filePath path to the file, relative to the owners file dir */ @@ -445,9 +445,9 @@ class Keymanager { } /** - * @brief Delete a single user's shareKey for a single file + * Delete a single user's shareKey for a single file */ - public static function delShareKey(\OC_FilesystemView $view, $userIds, $filePath) { + public static function delShareKey(\OC\Files\View $view, $userIds, $filePath) { $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; @@ -486,7 +486,7 @@ class Keymanager { } /** - * @brief recursively delete share keys from given users + * recursively delete share keys from given users * * @param string $dir directory * @param array $userIds user ids for which the share keys should be deleted @@ -512,11 +512,11 @@ class Keymanager { } /** - * @brief Make preparations to vars and filesystem for saving a keyfile + * Make preparations to vars and filesystem for saving a keyfile * @param string|boolean $path * @param string $basePath */ - public static function keySetPreparation(\OC_FilesystemView $view, $path, $basePath, $userId) { + public static function keySetPreparation(\OC\Files\View $view, $path, $basePath, $userId) { $targetPath = ltrim($path, '/'); @@ -542,7 +542,7 @@ class Keymanager { } /** - * @brief extract filename from share key name + * extract filename from share key name * @param string $shareKey (filename.userid.sharekey) * @return string|false filename or false */ diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7be82c313e..ae3df834e9 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -24,7 +24,7 @@ */ /** - * @brief Encryption proxy which handles filesystem operations before and after + * Encryption proxy which handles filesystem operations before and after * execution and encrypts, and handles keyfiles accordingly. Used for * webui. */ @@ -65,7 +65,7 @@ class Proxy extends \OC_FileProxy { return false; } - $view = new \OC_FilesystemView(''); + $view = new \OC\Files\View(''); $util = new Util($view, $userId); // for write operation we always encrypt the files, for read operations @@ -79,8 +79,8 @@ class Proxy extends \OC_FileProxy { } /** - * @param $path - * @param $data + * @param string $path + * @param string $data * @return bool */ public function preFile_put_contents($path, &$data) { @@ -90,7 +90,7 @@ class Proxy extends \OC_FileProxy { if (!is_resource($data)) { // get root view - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); // get relative path $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path); @@ -101,7 +101,7 @@ class Proxy extends \OC_FileProxy { // create random cache folder $cacheFolder = rand(); - $path_slices = explode('/', \OC_Filesystem::normalizePath($path)); + $path_slices = explode('/', \OC\Files\Filesystem::normalizePath($path)); $path_slices[2] = "cache/".$cacheFolder; $tmpPath = implode('/', $path_slices); @@ -125,7 +125,7 @@ class Proxy extends \OC_FileProxy { // in the post proxy $tmpFileInfo = $view->getFileInfo($tmpPath); if ( isset($tmpFileInfo['size']) ) { - self::$unencryptedSizes[\OC_Filesystem::normalizePath($path)] = $tmpFileInfo['size']; + self::$unencryptedSizes[\OC\Files\Filesystem::normalizePath($path)] = $tmpFileInfo['size']; } // remove our temp file @@ -144,15 +144,15 @@ class Proxy extends \OC_FileProxy { } /** - * @brief update file cache with the new unencrypted size after file was written + * update file cache with the new unencrypted size after file was written * @param string $path * @param mixed $result * @return mixed */ public function postFile_put_contents($path, $result) { - $normalizedPath = \OC_Filesystem::normalizePath($path); + $normalizedPath = \OC\Files\Filesystem::normalizePath($path); if ( isset(self::$unencryptedSizes[$normalizedPath]) ) { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $view->putFileInfo($normalizedPath, array('encrypted' => true, 'unencrypted_size' => self::$unencryptedSizes[$normalizedPath])); unset(self::$unencryptedSizes[$normalizedPath]); @@ -168,7 +168,7 @@ class Proxy extends \OC_FileProxy { public function postFile_get_contents($path, $data) { $plainData = null; - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); // init session $session = new \OCA\Encryption\Session($view); @@ -212,7 +212,7 @@ class Proxy extends \OC_FileProxy { } /** - * @brief remember initial fopen mode because sometimes it gets changed during the request + * remember initial fopen mode because sometimes it gets changed during the request * @param string $path path * @param string $mode type of access */ @@ -225,8 +225,8 @@ class Proxy extends \OC_FileProxy { /** - * @param $path - * @param $result + * @param string $path + * @param resource $result * @return resource */ public function postFopen($path, &$result) { @@ -261,8 +261,8 @@ class Proxy extends \OC_FileProxy { } /** - * @param $path - * @param $data + * @param string $path + * @param array $data * @return array */ public function postGetFileInfo($path, $data) { @@ -285,13 +285,13 @@ class Proxy extends \OC_FileProxy { } /** - * @param $path - * @param $size - * @return bool + * @param string $path + * @param int $size + * @return int|bool */ public function postFileSize($path, $size) { - $view = new \OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); $userId = Helper::getUser($path); $util = new Util($view, $userId); diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 3daaa06425..93be6691f9 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -36,8 +36,8 @@ class Session { /** - * @brief if session is started, check if ownCloud key pair is set up, if not create it - * @param \OC_FilesystemView $view + * if session is started, check if ownCloud key pair is set up, if not create it + * @param \OC\Files\View $view * * @note The ownCloud key pair is used to allow public link sharing even if encryption is enabled */ @@ -105,7 +105,7 @@ class Session { } /** - * @brief Sets user private key to session + * Sets user private key to session * @param string $privateKey * @return bool * @@ -120,8 +120,8 @@ class Session { } /** - * @brief Sets status of encryption app - * @param string $init INIT_SUCCESSFUL, INIT_EXECUTED, NOT_INOITIALIZED + * Sets status of encryption app + * @param string $init INIT_SUCCESSFUL, INIT_EXECUTED, NOT_INITIALIZED * @return bool * * @note this doesn not indicate of the init was successful, we just remeber the try! @@ -135,7 +135,7 @@ class Session { } /** - * @brief remove encryption keys and init status from session + * remove encryption keys and init status from session */ public function closeSession() { \OC::$session->remove('encryptionInitialized'); @@ -144,8 +144,8 @@ class Session { /** - * @brief Gets status if we already tried to initialize the encryption app - * @returns init status INIT_SUCCESSFUL, INIT_EXECUTED, NOT_INOITIALIZED + * Gets status if we already tried to initialize the encryption app + * @return string init status INIT_SUCCESSFUL, INIT_EXECUTED, NOT_INITIALIZED * * @note this doesn not indicate of the init was successful, we just remeber the try! */ @@ -158,8 +158,8 @@ class Session { } /** - * @brief Gets user or public share private key from session - * @returns string $privateKey The user's plaintext private key + * Gets user or public share private key from session + * @return string $privateKey The user's plaintext private key * */ public function getPrivateKey() { @@ -176,7 +176,7 @@ class Session { } /** - * @brief Sets public user private key to session + * Sets public user private key to session * @param string $privateKey * @return bool */ @@ -189,8 +189,8 @@ class Session { } /** - * @brief Gets public share private key from session - * @returns string $privateKey + * Gets public share private key from session + * @return string $privateKey * */ public function getPublicSharePrivateKey() { @@ -204,7 +204,7 @@ class Session { /** - * @brief Sets user legacy key to session + * Sets user legacy key to session * @param string $legacyKey * @return bool */ @@ -216,8 +216,8 @@ class Session { } /** - * @brief Gets user legacy key from session - * @returns string $legacyKey The user's plaintext legacy key + * Gets user legacy key from session + * @return string $legacyKey The user's plaintext legacy key * */ public function getLegacyKey() { diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index df5de55886..341114214d 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -31,7 +31,7 @@ namespace OCA\Encryption; /** - * @brief Provides 'crypt://' stream wrapper protocol. + * Provides 'crypt://' stream wrapper protocol. * @note We use a stream wrapper because it is the most secure way to handle * decrypted content transfers. There is no safe way to decrypt the entire file * somewhere on the server, so we have to encrypt and decrypt blocks on the fly. @@ -79,10 +79,10 @@ class Stream { private $privateKey; /** - * @param $path raw path relative to data/ - * @param $mode - * @param $options - * @param $opened_path + * @param string $path raw path relative to data/ + * @param string $mode + * @param int $options + * @param string $opened_path * @return bool */ public function stream_open($path, $mode, $options, &$opened_path) { @@ -91,7 +91,7 @@ class Stream { $this->newFile = false; if (!isset($this->rootView)) { - $this->rootView = new \OC_FilesystemView('/'); + $this->rootView = new \OC\Files\View('/'); } $this->session = new \OCA\Encryption\Session($this->rootView); @@ -179,15 +179,15 @@ class Stream { } /** - * @brief Returns the current position of the file pointer - * @return int position of the file pointer + * Returns the current position of the file pointer + * @return int position of the file pointer */ public function stream_tell() { return ftell($this->handle); } /** - * @param $offset + * @param int $offset * @param int $whence * @return bool true if fseek was successful, otherwise false */ @@ -202,7 +202,7 @@ class Stream { } /** - * @param $count + * @param int $count * @return bool|string * @throws \Exception */ @@ -246,7 +246,7 @@ class Stream { } /** - * @brief Encrypt and pad data ready for writing to disk + * Encrypt and pad data ready for writing to disk * @param string $plainData data to be encrypted * @param string $key key to use for encryption * @return string encrypted data on success, false on failure @@ -267,7 +267,7 @@ class Stream { } /** - * @brief Fetch the plain encryption key for the file and set it as plainKey property + * Fetch the plain encryption key for the file and set it as plainKey property * @internal param bool $generate if true, a new key will be generated if none can be found * @return bool true on key found and set, false on key not found and new key generated and set */ @@ -318,7 +318,7 @@ class Stream { } /** - * @brief Handle plain data from the stream, and write it in 8192 byte blocks + * Handle plain data from the stream, and write it in 8192 byte blocks * @param string $data data to be written to disk * @note the data will be written to the path stored in the stream handle, set in stream_open() * @note $data is only ever be a maximum of 8192 bytes long. This is set by PHP internally. stream_write() is called multiple times in a loop on data larger than 8192 bytes @@ -426,9 +426,9 @@ class Stream { /** - * @param $option - * @param $arg1 - * @param $arg2 + * @param int $option + * @param int $arg1 + * @param int|null $arg2 */ public function stream_set_option($option, $arg1, $arg2) { $return = false; @@ -454,7 +454,7 @@ class Stream { } /** - * @param $mode + * @param int $mode */ public function stream_lock($mode) { return flock($this->handle, $mode); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 6372ab31b6..d20efc3ac7 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -25,8 +25,8 @@ namespace OCA\Encryption; /** - * @brief Class for utilities relating to encrypted file storage system - * @param \OC_FilesystemView $view expected to have OC '/' as root path + * Class for utilities relating to encrypted file storage system + * @param \OC\Files\View $view expected to have OC '/' as root path * @param string $userId ID of the logged in user * @param int $client indicating status of client side encryption. Currently * unused, likely to become obsolete shortly @@ -38,7 +38,7 @@ class Util { const MIGRATION_IN_PROGRESS = -1; // migration is running const MIGRATION_OPEN = 0; // user still needs to be migrated - private $view; // OC_FilesystemView object for filesystem operations + private $view; // OC\Files\View object for filesystem operations private $userId; // ID of the user we use to encrypt/decrypt files private $keyId; // ID of the key we want to manipulate private $client; // Client side encryption mode flag @@ -53,8 +53,8 @@ class Util { private $isPublic; /** - * @param \OC_FilesystemView $view - * @param $userId + * @param \OC\Files\View $view + * @param string $userId * @param bool $client */ public function __construct($view, $userId, $client = false) { @@ -111,7 +111,7 @@ class Util { } /** - * @brief check if the users private & public key exists + * check if the users private & public key exists * @return boolean */ public function userKeysExists() { @@ -125,7 +125,7 @@ class Util { } /** - * @brief Sets up user folders and keys for serverside encryption + * Sets up user folders and keys for serverside encryption * * @param string $passphrase to encrypt server-stored private key with * @return bool @@ -222,7 +222,7 @@ class Util { } /** - * @brief Check whether pwd recovery is enabled for a given user + * Check whether pwd recovery is enabled for a given user * @return bool 1 = yes, 0 = no, false = no record * * @note If records are not being returned, check for a hidden space @@ -264,7 +264,7 @@ class Util { } /** - * @brief Enable / disable pwd recovery for a given user + * Enable / disable pwd recovery for a given user * @param bool $enabled Whether to enable or disable recovery * @return bool */ @@ -300,7 +300,7 @@ class Util { } /** - * @brief Find all files and their encryption status within a directory + * Find all files and their encryption status within a directory * @param string $directory The path of the parent directory to search * @param bool $found the founded files if called again * @return mixed false if 0 found, array on success. Keys: name, path @@ -421,7 +421,7 @@ class Util { } /** - * @brief Check if a given path identifies an encrypted file + * Check if a given path identifies an encrypted file * @param string $path * @return boolean */ @@ -463,7 +463,7 @@ class Util { } /** - * @brief get the file size of the unencrypted file + * get the file size of the unencrypted file * @param string $path absolute path * @return bool */ @@ -537,7 +537,7 @@ class Util { } /** - * @brief fix the file size of the encrypted file + * fix the file size of the encrypted file * @param string $path absolute path * @return boolean true / false if file is encrypted */ @@ -594,7 +594,7 @@ class Util { } /** - * @brief encrypt versions from given file + * encrypt versions from given file * @param array $filelist list of encrypted files, relative to data/user/files * @return boolean */ @@ -640,7 +640,7 @@ class Util { } /** - * @brief decrypt versions from given file + * decrypt versions from given file * @param string $filelist list of decrypted files, relative to data/user/files * @return boolean */ @@ -686,7 +686,7 @@ class Util { } /** - * @brief Decrypt all files + * Decrypt all files * @return bool */ public function decryptAll() { @@ -788,8 +788,8 @@ class Util { } if ($successful) { - $this->view->deleteAll($this->keyfilesPath); - $this->view->deleteAll($this->shareKeysPath); + $this->view->rename($this->keyfilesPath, $this->keyfilesPath . '.backup'); + $this->view->rename($this->shareKeysPath, $this->shareKeysPath . '.backup'); } \OC_FileProxy::$enabled = true; @@ -799,7 +799,7 @@ class Util { } /** - * @brief Encrypt all files in a directory + * Encrypt all files in a directory * @param string $dirPath the directory whose files will be encrypted * @param null $legacyPassphrase * @param null $newPassphrase @@ -926,7 +926,7 @@ class Util { } /** - * @brief Return important encryption related paths + * Return important encryption related paths * @param string $pathName Name of the directory to return the path of * @return string path */ @@ -970,7 +970,7 @@ class Util { } /** - * @brief Filter an array of UIDs to return only ones ready for sharing + * Filter an array of UIDs to return only ones ready for sharing * @param array $unfilteredUsers users to be checked for sharing readiness * @return array as multi-dimensional array. keys: ready, unready */ @@ -1017,7 +1017,7 @@ class Util { } /** - * @brief Decrypt a keyfile + * Decrypt a keyfile * @param string $filePath * @param string $privateKey * @return false|string @@ -1036,7 +1036,7 @@ class Util { } /** - * @brief Encrypt keyfile to multiple users + * Encrypt keyfile to multiple users * @param Session $session * @param array $users list of users which should be able to access the file * @param string $filePath path of the file to be shared @@ -1097,7 +1097,7 @@ class Util { } /** - * @brief Find, sanitise and format users sharing a file + * 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 @@ -1176,7 +1176,7 @@ class Util { } /** - * @brief set migration status + * set migration status * @param int $status * @return boolean */ @@ -1199,7 +1199,7 @@ class Util { } /** - * @brief start migration mode to initially encrypt users data + * start migration mode to initially encrypt users data * @return boolean */ public function beginMigration() { @@ -1221,7 +1221,7 @@ class Util { } /** - * @brief close migration mode after users data has been encrypted successfully + * close migration mode after users data has been encrypted successfully * @return boolean */ public function finishMigration() { @@ -1237,8 +1237,8 @@ class Util { } /** - * @brief check if files are already migrated to the encryption system - * @return migration status, false = in case of no record + * check if files are already migrated to the encryption system + * @return int|false migration status, false = in case of no record * @note If records are not being returned, check for a hidden space * at the start of the uid in db */ @@ -1288,7 +1288,7 @@ class Util { } /** - * @brief get uid of the owners of the file and the path to the file + * get uid of the owners of the file and the path to the file * @param string $path Path of the file to check * @throws \Exception * @note $shareFilePath must be relative to data/UID/files. Files @@ -1361,13 +1361,13 @@ class Util { return array( $fileOwnerUid, - \OC_Filesystem::normalizePath($filename) + \OC\Files\Filesystem::normalizePath($filename) ); } } /** - * @brief go recursively through a dir and collect all files and sub files. + * go recursively through a dir and collect all files and sub files. * @param string $dir relative to the users files folder * @return array with list of files relative to the users files folder */ @@ -1397,9 +1397,8 @@ class Util { } /** - * @brief get owner of the shared files. - * @param $id - * @internal param int $Id of a share + * get owner of the shared files. + * @param int $id ID of a share * @return string owner */ public function getOwnerFromSharedFile($id) { @@ -1479,7 +1478,7 @@ class Util { } /** - * @param $password + * @param string $password * @return bool */ public function checkRecoveryPassword($password) { @@ -1512,7 +1511,7 @@ class Util { } /** - * @brief add recovery key to all encrypted files + * add recovery key to all encrypted files */ public function addRecoveryKeys($path = '/') { $dirContent = $this->view->getDirectoryContent($this->keyfilesPath . $path); @@ -1522,7 +1521,7 @@ class Util { if ($item['type'] === 'dir') { $this->addRecoveryKeys($filePath . '/'); } else { - $session = new \OCA\Encryption\Session(new \OC_FilesystemView('/')); + $session = new \OCA\Encryption\Session(new \OC\Files\View('/')); $sharingEnabled = \OCP\Share::isEnabled(); // remove '.key' extension from path e.g. 'file.txt.key' to 'file.txt' $file = substr($filePath, 0, -4); @@ -1533,7 +1532,7 @@ class Util { } /** - * @brief remove recovery key to all encrypted files + * remove recovery key to all encrypted files */ public function removeRecoveryKeys($path = '/') { $dirContent = $this->view->getDirectoryContent($this->keyfilesPath . $path); @@ -1551,7 +1550,7 @@ class Util { } /** - * @brief decrypt given file with recovery key and encrypt it again to the owner and his new key + * decrypt given file with recovery key and encrypt it again to the owner and his new key * @param string $file * @param string $privateKey recovery key to decrypt the file */ @@ -1599,7 +1598,7 @@ class Util { } /** - * @brief collect all files and recover them one by one + * collect all files and recover them one by one * @param string $path to look for files keys * @param string $privateKey private recovery key which is used to decrypt the files */ @@ -1619,7 +1618,7 @@ class Util { } /** - * @brief recover users files in case of password lost + * recover users files in case of password lost * @param string $recoveryPassword */ public function recoverUsersFiles($recoveryPassword) { @@ -1638,8 +1637,8 @@ class Util { } /** - * @brief check if the file is stored on a system wide mount point - * @param $path relative to /data/user with leading '/' + * check if the file is stored on a system wide mount point + * @param string $path relative to /data/user with leading '/' * @return boolean */ public function isSystemWideMountPoint($path) { @@ -1655,7 +1654,7 @@ class Util { } /** - * @brief decrypt private key and add it to the current session + * decrypt private key and add it to the current session * @param array $params with 'uid' and 'password' * @return mixed session or false */ @@ -1683,7 +1682,7 @@ class Util { } /* - * @brief remove encryption related keys from the session + * remove encryption related keys from the session */ public function closeEncryptionSession() { $session = new \OCA\Encryption\Session($this->view); diff --git a/apps/files_encryption/settings-personal.php b/apps/files_encryption/settings-personal.php index 09e9df0535..e9875518f6 100644 --- a/apps/files_encryption/settings-personal.php +++ b/apps/files_encryption/settings-personal.php @@ -12,7 +12,7 @@ $tmpl = new OCP\Template('files_encryption', 'settings-personal'); $user = \OCP\USER::getUser(); -$view = new \OC_FilesystemView('/'); +$view = new \OC\Files\View('/'); $util = new \OCA\Encryption\Util($view, $user); $session = new \OCA\Encryption\Session($view); diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index 123943ea26..b22cd214ea 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -34,7 +34,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { public $dataUrl; public $dataShort; /** - * @var OC_FilesystemView + * @var OC\Files\View */ public $view; public $legacyEncryptedData; @@ -79,7 +79,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $this->genPublicKey = $keypair['publicKey']; $this->genPrivateKey = $keypair['privateKey']; - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); // remember files_trashbin state $this->stateFilesTrashbin = OC_App::isEnabled('files_trashbin'); @@ -157,7 +157,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $filename = 'tmp-' . uniqid() . '.test'; - $util = new Encryption\Util(new \OC_FilesystemView(), $this->userId); + $util = new Encryption\Util(new \OC\Files\View(), $this->userId); $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/'. $filename, $this->dataShort); @@ -206,7 +206,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief Test that data that is written by the crypto stream wrapper + * Test that data that is written by the crypto stream wrapper * @note Encrypted data is manually prepared and decrypted here to avoid dependency on success of stream_read * @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual * reassembly of its data @@ -216,7 +216,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // Generate a a random filename $filename = 'tmp-' . uniqid() . '.test'; - $util = new Encryption\Util(new \OC_FilesystemView(), $this->userId); + $util = new Encryption\Util(new \OC\Files\View(), $this->userId); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong . $this->dataLong); @@ -293,7 +293,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief Test that data that is read by the crypto stream wrapper + * Test that data that is read by the crypto stream wrapper */ function testSymmetricStreamDecryptShortFileContent() { @@ -388,7 +388,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test decryption using legacy blowfish method + * test decryption using legacy blowfish method */ function testLegacyDecryptShort() { @@ -402,7 +402,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test decryption using legacy blowfish method + * test decryption using legacy blowfish method */ function testLegacyDecryptLong() { @@ -660,9 +660,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { /** - * @brief encryption using legacy blowfish method + * encryption using legacy blowfish method * @param string $data data to encrypt - * @param $passwd string password + * @param string $passwd password * @return string */ function legacyEncrypt($data, $passwd) { diff --git a/apps/files_encryption/tests/hooks.php b/apps/files_encryption/tests/hooks.php index 047084ca2c..fcb369c723 100644 --- a/apps/files_encryption/tests/hooks.php +++ b/apps/files_encryption/tests/hooks.php @@ -32,7 +32,7 @@ use OCA\Encryption; /** * Class Test_Encryption_Hooks - * @brief this class provide basic hook app tests + * this class provide basic hook app tests */ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { @@ -40,7 +40,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2"; /** - * @var \OC_FilesystemView + * @var \OC\Files\View */ public $user1View; // view on /data/user1/files public $user2View; // view on /data/user2/files @@ -83,9 +83,9 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1); // init filesystem view - $this->user1View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '/files'); - $this->user2View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '/files'); - $this->rootView = new \OC_FilesystemView('/'); + $this->user1View = new \OC\Files\View('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '/files'); + $this->user2View = new \OC\Files\View('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '/files'); + $this->rootView = new \OC\Files\View('/'); // init short data $this->data = 'hats'; @@ -259,7 +259,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { } /** - * @brief test rename operation + * test rename operation */ function testRenameHook() { diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 0caf12e91a..2bd2ddc8e6 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -29,7 +29,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { public $pass; public $stateFilesTrashbin; /** - * @var OC_FilesystemView + * @var OC\Files\View */ public $view; public $randomKey; @@ -68,7 +68,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $this->genPublicKey = $keypair['publicKey']; $this->genPrivateKey = $keypair['privateKey']; - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); \OC_User::setUserId(\Test_Encryption_Keymanager::TEST_USER); $this->userId = \Test_Encryption_Keymanager::TEST_USER; @@ -257,4 +257,4 @@ class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager { public static function testGetFilenameFromShareKey($sharekey) { return self::getFilenameFromShareKey($sharekey); } -} \ No newline at end of file +} diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index 647ee955eb..8d6bc81b08 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -33,7 +33,7 @@ use OCA\Encryption; /** * Class Test_Encryption_Proxy - * @brief this class provide basic proxy app tests + * this class provide basic proxy app tests */ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase { @@ -42,7 +42,7 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase { public $userId; public $pass; /** - * @var \OC_FilesystemView + * @var \OC\Files\View */ public $view; // view in /data/user/files public $rootView; // view on /data/user @@ -75,8 +75,8 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase { $this->pass = \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1; // init filesystem view - $this->view = new \OC_FilesystemView('/'. \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files'); - $this->rootView = new \OC_FilesystemView('/'. \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 ); + $this->view = new \OC\Files\View('/'. \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '/files'); + $this->rootView = new \OC\Files\View('/'. \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 ); // init short data $this->data = 'hats'; @@ -91,7 +91,7 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test if postFileSize returns the unencrypted file size + * test if postFileSize returns the unencrypted file size */ function testPostFileSize() { diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 512671c576..bb3d7505a5 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -48,7 +48,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { public $filename; public $dataShort; /** - * @var OC_FilesystemView + * @var OC\Files\View */ public $view; public $folder1; @@ -92,7 +92,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { function setUp() { $this->dataShort = 'hats'; - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); $this->folder1 = '/folder1'; $this->subfolder = '/subfolder1'; @@ -669,7 +669,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // login as admin \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); + $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); // check if recovery password match $this->assertTrue($util->checkRecoveryPassword('test123')); @@ -777,7 +777,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // login as user2 \Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); + $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2); // enable recovery for admin $this->assertTrue($util->setRecoveryForUser(1)); @@ -959,7 +959,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { /** - * @brief test moving a shared file out of the Shared folder + * test moving a shared file out of the Shared folder */ function testRename() { diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php index fed2e7d89d..5df9cdbe1f 100644 --- a/apps/files_encryption/tests/stream.php +++ b/apps/files_encryption/tests/stream.php @@ -33,7 +33,7 @@ use OCA\Encryption; /** * Class Test_Encryption_Stream - * @brief this class provide basic stream tests + * this class provide basic stream tests */ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { @@ -42,7 +42,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { public $userId; public $pass; /** - * @var \OC_FilesystemView + * @var \OC\Files\View */ public $view; public $dataShort; @@ -71,7 +71,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { $this->pass = \Test_Encryption_Stream::TEST_ENCRYPTION_STREAM_USER1; // init filesystem view - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); // init short data $this->dataShort = 'hats'; @@ -183,7 +183,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test if stream wrapper can read files outside from the data folder + * test if stream wrapper can read files outside from the data folder */ function testStreamFromLocalFile() { diff --git a/apps/files_encryption/tests/trashbin.php b/apps/files_encryption/tests/trashbin.php index 2f9ecfd9d5..5d54b7db24 100755 --- a/apps/files_encryption/tests/trashbin.php +++ b/apps/files_encryption/tests/trashbin.php @@ -34,7 +34,7 @@ use OCA\Encryption; /** * Class Test_Encryption_Trashbin - * @brief this class provide basic trashbin app tests + * this class provide basic trashbin app tests */ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { @@ -43,7 +43,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { public $userId; public $pass; /** - * @var \OC_FilesystemView + * @var \OC\Files\View */ public $view; public $dataShort; @@ -81,7 +81,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { $this->pass = \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1; // init filesystem view - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); // init short data $this->dataShort = 'hats'; @@ -114,7 +114,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test delete file + * test delete file */ function testDeleteFile() { @@ -186,7 +186,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test restore file + * test restore file * * @depends testDeleteFile */ @@ -218,7 +218,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test delete file forever + * test delete file forever */ function testPermanentDeleteFile() { diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 88ded7ec40..a4dcc5cc8b 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -29,7 +29,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { public $publicKeyDir; public $pass; /** - * @var OC_FilesystemView + * @var OC\Files\View */ public $view; public $keyfilesPath; @@ -92,7 +92,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $this->privateKeyPath = $this->encryptionDir . '/' . $this->userId . '.private.key'; // e.g. data/admin/admin.private.key - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); $this->util = new Encryption\Util($this->view, $this->userId); @@ -121,7 +121,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test that paths set during User construction are correct + * test that paths set during User construction are correct */ function testKeyPaths() { $util = new Encryption\Util($this->view, $this->userId); @@ -136,7 +136,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test detection of encrypted files + * test detection of encrypted files */ function testIsEncryptedPath() { @@ -171,7 +171,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test setup of encryption directories + * test setup of encryption directories */ function testSetupServerSide() { $this->assertEquals(true, $this->util->setupServerSide($this->pass)); @@ -179,14 +179,14 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test checking whether account is ready for encryption, + * test checking whether account is ready for encryption, */ function testUserIsReady() { $this->assertEquals(true, $this->util->ready()); } /** - * @brief test checking whether account is not ready for encryption, + * test checking whether account is not ready for encryption, */ // function testUserIsNotReady() { // $this->view->unlink($this->publicKeyDir); @@ -200,12 +200,12 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { /** * @medium - * @brief test checking whether account is not ready for encryption, + * test checking whether account is not ready for encryption, */ function testIsLegacyUser() { \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); - $userView = new \OC_FilesystemView('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); + $userView = new \OC\Files\View('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -279,7 +279,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { } /** -< * @brief Test that data that is read by the crypto stream wrapper +< * Test that data that is read by the crypto stream wrapper */ function testGetFileSize() { \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1); @@ -384,7 +384,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $params = array('uid' => \OCP\User::getUser(), 'password' => \OCP\User::getUser()); - $view = new OC_FilesystemView('/'); + $view = new OC\Files\View('/'); $util = new \OCA\Encryption\Util($view, \OCP\User::getUser()); $result = $util->initEncryption($params); @@ -413,8 +413,16 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { // file should no longer be encrypted $this->assertEquals(0, $fileInfoUnencrypted['encrypted']); + // check if the keys where moved to the backup location + $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/keyfiles.backup')); + $this->assertTrue($this->view->file_exists($this->userId . '/files_encryption/keyfiles.backup/' . $filename . '.key')); + $this->assertTrue($this->view->is_dir($this->userId . '/files_encryption/share-keys.backup')); + $this->assertTrue($this->view->file_exists($this->userId . '/files_encryption/share-keys.backup/' . $filename . '.' . $user . '.shareKey')); + // cleanup $this->view->unlink($this->userId . '/files/' . $filename); + $this->view->deleteAll($this->userId . '/files_encryption/keyfiles.backup'); + $this->view->deleteAll($this->userId . '/files_encryption/share-keys.backup'); OC_App::enable('files_encryption'); } @@ -485,8 +493,11 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/keyfiles/')); $this->assertFalse($this->view->is_dir($this->userId . '/files_encryption/share-keys/')); + //cleanup $this->view->unlink($this->userId . '/files/' . $file1); $this->view->unlink($this->userId . '/files/' . $file2); + $this->view->deleteAll($this->userId . '/files_encryption/keyfiles.backup'); + $this->view->deleteAll($this->userId . '/files_encryption/share-keys.backup'); } @@ -496,8 +507,8 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { function testEncryptLegacyFiles() { \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); - $userView = new \OC_FilesystemView('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); - $view = new \OC_FilesystemView('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER . '/files'); + $userView = new \OC\Files\View('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER); + $view = new \OC\Files\View('/' . \Test_Encryption_Util::TEST_ENCRYPTION_UTIL_LEGACY_USER . '/files'); // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -543,7 +554,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { } /** - * @param $user + * @param string $user * @param bool $create * @param bool $password */ @@ -584,7 +595,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { * to be able to test the migration path * * @param integer $status needed migration status for test - * @param $user for which user the status should be set + * @param string $user for which user the status should be set * @return boolean */ private function setMigrationStatus($status, $user) { diff --git a/apps/files_encryption/tests/webdav.php b/apps/files_encryption/tests/webdav.php index 1fe4c13d59..d33dc58cf9 100755 --- a/apps/files_encryption/tests/webdav.php +++ b/apps/files_encryption/tests/webdav.php @@ -34,7 +34,7 @@ use OCA\Encryption; /** * Class Test_Encryption_Webdav * - * @brief this class provide basic webdav tests for PUT,GET and DELETE + * this class provide basic webdav tests for PUT,GET and DELETE */ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { @@ -43,7 +43,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { public $userId; public $pass; /** - * @var \OC_FilesystemView + * @var \OC\Files\View */ public $view; public $dataShort; @@ -82,7 +82,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { $this->pass = \Test_Encryption_Webdav::TEST_ENCRYPTION_WEBDAV_USER1; // init filesystem view - $this->view = new \OC_FilesystemView('/'); + $this->view = new \OC\Files\View('/'); // init short data $this->dataShort = 'hats'; @@ -112,7 +112,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { } /** - * @brief test webdav put random file + * test webdav put random file */ function testWebdavPUT() { @@ -167,7 +167,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { } /** - * @brief test webdav get random file + * test webdav get random file * * @depends testWebdavPUT */ @@ -190,7 +190,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { } /** - * @brief test webdav delete random file + * test webdav delete random file * @depends testWebdavGET */ function testWebdavDELETE($filename) { @@ -216,7 +216,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { } /** - * @brief handle webdav request + * handle webdav request * * @param bool $body * diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php index 003665486f..e8ed8950c3 100644 --- a/apps/files_external/appinfo/app.php +++ b/apps/files_external/appinfo/app.php @@ -70,7 +70,7 @@ OC_Mount_Config::registerBackend('\OC\Files\Storage\Dropbox', array( OC_Mount_Config::registerBackend('\OC\Files\Storage\FTP', array( 'backend' => 'FTP', 'configuration' => array( - 'host' => (string)$l->t('URL'), + 'host' => (string)$l->t('Host'), 'user' => (string)$l->t('Username'), 'password' => '*'.$l->t('Password'), 'root' => '&'.$l->t('Root'), @@ -108,7 +108,7 @@ if (!OC_Util::runningOnWindows()) { OC_Mount_Config::registerBackend('\OC\Files\Storage\SMB', array( 'backend' => 'SMB / CIFS', 'configuration' => array( - 'host' => (string)$l->t('URL'), + 'host' => (string)$l->t('Host'), 'user' => (string)$l->t('Username'), 'password' => '*'.$l->t('Password'), 'share' => (string)$l->t('Share'), @@ -118,7 +118,7 @@ if (!OC_Util::runningOnWindows()) { 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'), + 'host' => (string)$l->t('Host'), 'username_as_share' => '!'.$l->t('Username as share'), 'share' => '&'.$l->t('Share'), 'root' => '&'.$l->t('Root')), @@ -148,7 +148,7 @@ OC_Mount_Config::registerBackend('\OC\Files\Storage\OwnCloud', array( OC_Mount_Config::registerBackend('\OC\Files\Storage\SFTP', array( 'backend' => 'SFTP', 'configuration' => array( - 'host' => (string)$l->t('URL'), + 'host' => (string)$l->t('Host'), 'user' => (string)$l->t('Username'), 'password' => '*'.$l->t('Password'), 'root' => '&'.$l->t('Root')))); diff --git a/apps/files_external/l10n/ar.php b/apps/files_external/l10n/ar.php index 5bef941c19..eb1150eb95 100644 --- a/apps/files_external/l10n/ar.php +++ b/apps/files_external/l10n/ar.php @@ -1,10 +1,11 @@ "المكان", -"URL" => "عنوان الموقع", +"Host" => "المضيف", "Username" => "إسم المستخدم", "Password" => "كلمة السر", "Share" => "شارك", +"URL" => "عنوان الموقع", "Saved" => "حفظ", "Folder name" => "اسم المجلد", "Options" => "خيارات", diff --git a/apps/files_external/l10n/ast.php b/apps/files_external/l10n/ast.php index add4981915..faf0388dd9 100644 --- a/apps/files_external/l10n/ast.php +++ b/apps/files_external/l10n/ast.php @@ -2,16 +2,69 @@ $TRANSLATIONS = array( "Local" => "Llocal", "Location" => "Llocalización", -"URL" => "URL", +"Amazon S3" => "Amazon S3", +"Key" => "Clave", +"Secret" => "Secretu", +"Bucket" => "Depósitu", +"Amazon S3 and compliant" => "Amazon S3 y compatibilidá", +"Access Key" => "Clave d'accesu", +"Secret Key" => "Clave Secreta", +"Hostname (optional)" => "Nome d'equipu (opcional)", +"Port (optional)" => "Puertu (opcional)", +"Region (optional)" => "Rexón (opcional)", +"Enable SSL" => "Habilitar SSL", +"Enable Path Style" => "Habilitar Estilu de ruta", +"App key" => "App principal", +"App secret" => "App secreta", +"Host" => "Sirvidor", "Username" => "Nome d'usuariu", "Password" => "Contraseña", +"Root" => "Raíz", +"Secure ftps://" => "Secure ftps://", +"Client ID" => "ID de veceru", +"Client secret" => "Veceru secretu", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "Nome d'usuariu (necesariu)", +"Bucket (required)" => "Depósitu (necesariu)", +"Region (optional for OpenStack Object Storage)" => "Rexón (opcional pa OpenStack Object Storage)", +"API Key (required for Rackspace Cloud Files)" => "Clave API (necesaria pa Rackspace Cloud Files)", +"Tenantname (required for OpenStack Object Storage)" => "Nome d'inquilín (necesariu pa OpenStack Object Storage)", +"Password (required for OpenStack Object Storage)" => "Contraseña (necesaria pa OpenStack Object Storage)", +"Service Name (required for OpenStack Object Storage)" => "Nome de Serviciu (necesariu pa OpenStack Object Storage)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "URL d'identidá de puntu final (necesariu pa OpenStack Object Storage)", +"Timeout of HTTP requests in seconds (optional)" => "Tiempu d'espera de peticiones HTTP en segundos (opcional)", "Share" => "Compartir", +"SMB / CIFS using OC login" => "SMB / CIFS usando accesu OC", +"Username as share" => "Nome d'usuariu como Compartición", +"URL" => "URL", +"Secure https://" => "Secure https://", +"Remote subfolder" => "Subcarpeta remota", +"Access granted" => "Accesu concedíu", +"Error configuring Dropbox storage" => "Fallu configurando l'almacenamientu de Dropbox", +"Grant access" => "Conceder accesu", +"Please provide a valid Dropbox app key and secret." => "Por favor, proporciona una clave válida de l'app Dropbox y una clave secreta.", +"Error configuring Google Drive storage" => "Fallu configurando l'almacenamientu de Google Drive", "Saved" => "Guardáu", +"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 nun ta activáu o instaláu. Nun pue montase %s. Pídi-y al alministrador de sistema que lu 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 nun ta activáu o instaláu. Nun pue montase %s. Pídi-y al alministrador de sistema que lu instale.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Nota: \"%s\" nun ta instaláu. Nun pue montase %s. Pídi-y al alministrador de sistema que lu instale.", +"External Storage" => "Almacenamientu esternu", "Folder name" => "Nome de la carpeta", +"External storage" => "Almacenamientu esternu", "Configuration" => "Configuración", "Options" => "Opciones", +"Available for" => "Disponible pa", +"Add storage" => "Amestar almacenamientu", +"No user or group" => "Nengún usuariu o grupu", +"All Users" => "Tolos usuarios", "Groups" => "Grupos", "Users" => "Usuarios", -"Delete" => "Desaniciar" +"Delete" => "Desaniciar", +"Enable User External Storage" => "Habilitar almacenamientu esterno d'usuariu", +"Allow users to mount the following external storage" => "Permitir a los usuarios montar el siguiente almacenamientu esternu", +"SSL root certificates" => "Certificaos raíz SSL", +"Import Root Certificate" => "Importar certificáu raíz" ); $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 0969184383..13e43314bd 100644 --- a/apps/files_external/l10n/bg_BG.php +++ b/apps/files_external/l10n/bg_BG.php @@ -1,10 +1,10 @@ "Място", -"URL" => "Уеб адрес", "Username" => "Потребител", "Password" => "Парола", "Share" => "Споделяне", +"URL" => "Уеб адрес", "Access granted" => "Достъпът е даден", "Grant access" => "Даване на достъп", "External Storage" => "Външно хранилище", diff --git a/apps/files_external/l10n/bn_BD.php b/apps/files_external/l10n/bn_BD.php index 3b1978a568..f1ada4b476 100644 --- a/apps/files_external/l10n/bn_BD.php +++ b/apps/files_external/l10n/bn_BD.php @@ -1,10 +1,11 @@ "াবস্থান", -"URL" => "URL", +"Host" => "হোস্ট", "Username" => "ব্যবহারকারী", "Password" => "কূটশব্দ", "Share" => "ভাগাভাগি কর", +"URL" => "URL", "Access granted" => "অধিগমনের অনুমতি প্রদান করা হলো", "Error configuring Dropbox storage" => "Dropbox সংরক্ষণাগার নির্ধারণ করতে সমস্যা ", "Grant access" => "অধিগমনের অনুমতি প্রদান কর", diff --git a/apps/files_external/l10n/ca.php b/apps/files_external/l10n/ca.php index e49f26c353..e349dfe45e 100644 --- a/apps/files_external/l10n/ca.php +++ b/apps/files_external/l10n/ca.php @@ -2,10 +2,11 @@ $TRANSLATIONS = array( "Local" => "Local", "Location" => "Ubicació", -"URL" => "URL", +"Host" => "Equip remot", "Username" => "Nom d'usuari", "Password" => "Contrasenya", "Share" => "Comparteix", +"URL" => "URL", "Access granted" => "S'ha concedit l'accés", "Error configuring Dropbox storage" => "Error en configurar l'emmagatzemament Dropbox", "Grant access" => "Concedeix accés", diff --git a/apps/files_external/l10n/cs_CZ.php b/apps/files_external/l10n/cs_CZ.php index 4cfefbde05..2d1116ed0f 100644 --- a/apps/files_external/l10n/cs_CZ.php +++ b/apps/files_external/l10n/cs_CZ.php @@ -13,17 +13,19 @@ $TRANSLATIONS = array( "Enable SSL" => "Povolit SSL", "App key" => "Klíč aplikace", "App secret" => "Tajemství aplikace", -"URL" => "URL", +"Host" => "Počítač", "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ář", +"URL" => "URL", "Secure https://" => "Zabezpečené https://", "Remote subfolder" => "Vzdálený podadresář", "Access granted" => "Přístup povolen", diff --git a/apps/files_external/l10n/cy_GB.php b/apps/files_external/l10n/cy_GB.php index 9b5d97a48a..39822fcd38 100644 --- a/apps/files_external/l10n/cy_GB.php +++ b/apps/files_external/l10n/cy_GB.php @@ -1,10 +1,10 @@ "Lleoliad", -"URL" => "URL", "Username" => "Enw defnyddiwr", "Password" => "Cyfrinair", "Share" => "Rhannu", +"URL" => "URL", "Groups" => "Grwpiau", "Users" => "Defnyddwyr", "Delete" => "Dileu" diff --git a/apps/files_external/l10n/da.php b/apps/files_external/l10n/da.php index a0e8510789..2d235747ad 100644 --- a/apps/files_external/l10n/da.php +++ b/apps/files_external/l10n/da.php @@ -6,7 +6,7 @@ $TRANSLATIONS = array( "Key" => "Nøgle", "Secret" => "Hemmelighed", "Secret Key" => "Hemmelig Nøgle ", -"URL" => "URL", +"Host" => "Host", "Username" => "Brugernavn", "Password" => "Kodeord", "Root" => "Root", @@ -15,6 +15,7 @@ $TRANSLATIONS = array( "Client secret" => "Klient hemmelighed", "OpenStack Object Storage" => "OpenStack Object Storage", "Share" => "Del", +"URL" => "URL", "Secure https://" => "Sikker https://", "Access granted" => "Adgang godkendt", "Error configuring Dropbox storage" => "Fejl ved konfiguration af Dropbox plads", diff --git a/apps/files_external/l10n/de.php b/apps/files_external/l10n/de.php index c41cef968f..03f6f05abb 100644 --- a/apps/files_external/l10n/de.php +++ b/apps/files_external/l10n/de.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Pfad-Stil aktivieren", "App key" => "App-Schlüssel", "App secret" => "Geheime Zeichenkette der App", -"URL" => "URL", +"Host" => "Host", "Username" => "Benutzername", "Password" => "Passwort", "Root" => "Root", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Teilen", "SMB / CIFS using OC login" => "´", "Username as share" => "Benutzername als Freigabe", +"URL" => "URL", "Secure https://" => "Sicherer HTTPS://", "Remote subfolder" => "Remote-Unterordner:", "Access granted" => "Zugriff gestattet", diff --git a/apps/files_external/l10n/de_CH.php b/apps/files_external/l10n/de_CH.php index 6d7366fe28..4e0ac1f3a0 100644 --- a/apps/files_external/l10n/de_CH.php +++ b/apps/files_external/l10n/de_CH.php @@ -1,10 +1,11 @@ "Ort", -"URL" => "URL", +"Host" => "Host", "Username" => "Benutzername", "Password" => "Passwort", "Share" => "Freigeben", +"URL" => "URL", "Access granted" => "Zugriff gestattet", "Error configuring Dropbox storage" => "Fehler beim Einrichten von Dropbox", "Grant access" => "Zugriff gestatten", diff --git a/apps/files_external/l10n/de_DE.php b/apps/files_external/l10n/de_DE.php index 1119a0f875..286250f868 100644 --- a/apps/files_external/l10n/de_DE.php +++ b/apps/files_external/l10n/de_DE.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Pfad-Stil aktivieren", "App key" => "App-Schlüssel", "App secret" => "Geheime Zeichenkette der App", -"URL" => "URL", +"Host" => "Host", "Username" => "Benutzername", "Password" => "Passwort", "Root" => "Root", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Teilen", "SMB / CIFS using OC login" => "Zeitüberschreitung von HTTP-Anfragen in Sekunden (Optional)", "Username as share" => "Benutzername als Freigabe", +"URL" => "URL", "Secure https://" => "Sicherer HTTPS://", "Remote subfolder" => "Remote-Unterordner:", "Access granted" => "Zugriff gestattet", diff --git a/apps/files_external/l10n/el.php b/apps/files_external/l10n/el.php index 351468a36d..09d39a9e3c 100644 --- a/apps/files_external/l10n/el.php +++ b/apps/files_external/l10n/el.php @@ -2,23 +2,53 @@ $TRANSLATIONS = array( "Local" => "Τοπικός", "Location" => "Τοποθεσία", -"URL" => "URL", +"Key" => "Κλειδί", +"Secret" => "Μυστικό", +"Access Key" => "Κλειδί πρόσβασης", +"Secret Key" => "Μυστικό κλειδί", +"Hostname (optional)" => "Όνομα μηχανήματος (προαιρετικά)", +"Port (optional)" => "Πόρτα (προαιρετικά)", +"Region (optional)" => "Περιοχή (προαιρετικά)", +"Enable SSL" => "Ενεργοποίηση SSL", +"Enable Path Style" => "Ενεργοποίηση μορφής διαδρομής", +"App key" => "Κλειδί εφαρμογής", +"Host" => "Διακομιστής", "Username" => "Όνομα χρήστη", "Password" => "Κωδικός πρόσβασης", +"Root" => "Root", +"Secure ftps://" => "Ασφαλής ftps://", +"Client ID" => "ID πελάτη", +"Client secret" => "Μυστικό πελάτη", +"OpenStack Object Storage" => "Αποθήκη αντικειμένων OpenStack", "Username (required)" => "Όνομα χρήστη (απαιτείται)", +"Region (optional for OpenStack Object Storage)" => "Περιοχή (προαιρετικά για την αποθήκευση αντικειμένων OpenStack)", +"API Key (required for Rackspace Cloud Files)" => "Κλειδί API (απαιτείται για αρχεία Rackspace Cloud)", +"Password (required for OpenStack Object Storage)" => "Μυστικός κωδικός (απαιτείται για την αποθήκευση αντικειμένων OpenStack)", +"Service Name (required for OpenStack Object Storage)" => "Όνομα υπηρεσίας (απαιτείται για την αποθήκευση αντικειμένων OpenStack)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "Διεύθυνση URL της ταυτότητας τελικού σημείου (απαιτείται για την αποθήκευση αντικειμένων OpenStack)", +"Timeout of HTTP requests in seconds (optional)" => "Χρονικό όριο των αιτήσεων HTTP σε δευτερόλεπτα (προαιρετικά)", "Share" => "Διαμοιράστε", +"SMB / CIFS using OC login" => "SMB / CIFS χρησιμοποιώντας λογαριασμό OC", +"URL" => "URL", +"Secure https://" => "Ασφαλής σύνδεση https://", +"Remote subfolder" => "Απομακρυσμένος υποφάκελος", "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 ", "Saved" => "Αποθηκεύτηκαν", +"Note: " => "Σημείωση: ", " 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." => "Σημείωση: Η υποστήριξη cURL στην PHP δεν είναι ενεργοποιημένη ή εγκατεστημένη. Η προσάρτηση του %s δεν είναι δυνατή. Παρακαλώ ζητήστε από τον διαχειριστή συστημάτων σας να την εγκαταστήσει.", +"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." => "Σημείωση: Η υποστήριξη FTP στην PHP δεν είναι ενεργοποιημένη ή εγκατεστημένη. Δεν είναι δυνατή η προσάρτηση του %s. Παρακαλώ ζητήστε από τον διαχειριστή συστημάτων σας να την εγκαταστήσει.", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "Σημείωση: Η επέκταση \"%s\" δεν είναι εγκατεστημένη. Δεν είναι δυνατή η προσάρτηση %s. Παρακαλώ ζητήστε από τον διαχειριστή συστημάτων σας να την εγκαταστήσει.", "External Storage" => "Εξωτερικό Αποθηκευτικό Μέσο", "Folder name" => "Όνομα φακέλου", "External storage" => "Εξωτερική αποθήκευση", "Configuration" => "Ρυθμίσεις", "Options" => "Επιλογές", +"Available for" => "Διαθέσιμο για", "Add storage" => "Προσθηκη αποθηκευσης", "No user or group" => "Μη διαθέσιμος χρήστης ή ομάδα", "All Users" => "Όλοι οι Χρήστες", diff --git a/apps/files_external/l10n/en_GB.php b/apps/files_external/l10n/en_GB.php index 5a0e2456ac..d4229c607e 100644 --- a/apps/files_external/l10n/en_GB.php +++ b/apps/files_external/l10n/en_GB.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Enable Path Style", "App key" => "App key", "App secret" => "App secret", -"URL" => "URL", +"Host" => "Host", "Username" => "Username", "Password" => "Password", "Root" => "Root", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Share", "SMB / CIFS using OC login" => "SMB / CIFS using OC login", "Username as share" => "Username as share", +"URL" => "URL", "Secure https://" => "Secure https://", "Remote subfolder" => "Remote subfolder", "Access granted" => "Access granted", diff --git a/apps/files_external/l10n/eo.php b/apps/files_external/l10n/eo.php index d8915b49b0..d3ca5a5add 100644 --- a/apps/files_external/l10n/eo.php +++ b/apps/files_external/l10n/eo.php @@ -1,10 +1,11 @@ "Loko", -"URL" => "URL", +"Host" => "Gastigo", "Username" => "Uzantonomo", "Password" => "Pasvorto", "Share" => "Kunhavigi", +"URL" => "URL", "Access granted" => "Alirpermeso donita", "Error configuring Dropbox storage" => "Eraro dum agordado de la memorservo Dropbox", "Grant access" => "Doni alirpermeson", diff --git a/apps/files_external/l10n/es.php b/apps/files_external/l10n/es.php index 3c18b18057..bbbe0a8c61 100644 --- a/apps/files_external/l10n/es.php +++ b/apps/files_external/l10n/es.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Habilitar Estilo de Ruta", "App key" => "App principal", "App secret" => "App secreta", -"URL" => "URL", +"Host" => "Servidor", "Username" => "Nombre de usuario", "Password" => "Contraseña", "Root" => "Raíz", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Compartir", "SMB / CIFS using OC login" => "SMB / CIFS usando acceso OC", "Username as share" => "Nombre de Usuario como compartir", +"URL" => "URL", "Secure https://" => "Secure https://", "Remote subfolder" => "Subcarpeta remota", "Access granted" => "Acceso concedido", diff --git a/apps/files_external/l10n/es_AR.php b/apps/files_external/l10n/es_AR.php index c380c6d0d9..dfb53d9a78 100644 --- a/apps/files_external/l10n/es_AR.php +++ b/apps/files_external/l10n/es_AR.php @@ -1,10 +1,11 @@ "Ubicación", -"URL" => "URL", +"Host" => "Servidor", "Username" => "Nombre de usuario", "Password" => "Contraseña", "Share" => "Compartir", +"URL" => "URL", "Access granted" => "Acceso permitido", "Error configuring Dropbox storage" => "Error al configurar el almacenamiento de Dropbox", "Grant access" => "Permitir acceso", diff --git a/apps/files_external/l10n/es_MX.php b/apps/files_external/l10n/es_MX.php index 73ce835910..7e28798f58 100644 --- a/apps/files_external/l10n/es_MX.php +++ b/apps/files_external/l10n/es_MX.php @@ -1,10 +1,11 @@ "Ubicación", -"URL" => "URL", +"Host" => "Servidor", "Username" => "Nombre de usuario", "Password" => "Contraseña", "Share" => "Compartir", +"URL" => "URL", "Access granted" => "Acceso concedido", "Error configuring Dropbox storage" => "Error configurando el almacenamiento de Dropbox", "Grant access" => "Conceder acceso", diff --git a/apps/files_external/l10n/et_EE.php b/apps/files_external/l10n/et_EE.php index e5fc7c6937..7344441197 100644 --- a/apps/files_external/l10n/et_EE.php +++ b/apps/files_external/l10n/et_EE.php @@ -2,10 +2,11 @@ $TRANSLATIONS = array( "Local" => "Kohalik", "Location" => "Asukoht", -"URL" => "URL", +"Host" => "Host", "Username" => "Kasutajanimi", "Password" => "Parool", "Share" => "Jaga", +"URL" => "URL", "Access granted" => "Ligipääs on antud", "Error configuring Dropbox storage" => "Viga Dropboxi salvestusruumi seadistamisel", "Grant access" => "Anna ligipääs", diff --git a/apps/files_external/l10n/eu.php b/apps/files_external/l10n/eu.php index 5b28791786..ef29ba0484 100644 --- a/apps/files_external/l10n/eu.php +++ b/apps/files_external/l10n/eu.php @@ -1,26 +1,36 @@ "Bertakoa", "Location" => "Kokapena", -"URL" => "URL", +"Amazon S3" => "Amazon S3", +"Port (optional)" => "Portua (hautazkoa)", +"Enable SSL" => "Gaitu SSL", +"Host" => "Hostalaria", "Username" => "Erabiltzaile izena", "Password" => "Pasahitza", "Share" => "Partekatu", +"URL" => "URL", "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", +"Saved" => "Gordeta", +"Note: " => "Oharra:", +" and " => "eta", "External Storage" => "Kanpoko Biltegiratzea", "Folder name" => "Karpetaren izena", "External storage" => "Kanpoko biltegiratzea", "Configuration" => "Konfigurazioa", "Options" => "Aukerak", "Add storage" => "Gehitu biltegiratzea", +"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 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/fa.php b/apps/files_external/l10n/fa.php index 6bf8ce8af5..674a728733 100644 --- a/apps/files_external/l10n/fa.php +++ b/apps/files_external/l10n/fa.php @@ -1,10 +1,11 @@ "محل", -"URL" => "آدرس", +"Host" => "میزبانی", "Username" => "نام کاربری", "Password" => "گذرواژه", "Share" => "اشتراک‌گذاری", +"URL" => "آدرس", "Access granted" => "مجوز دسترسی صادر شد", "Error configuring Dropbox storage" => "خطا به هنگام تنظیم فضای دراپ باکس", "Grant access" => " مجوز اعطا دسترسی", diff --git a/apps/files_external/l10n/fi_FI.php b/apps/files_external/l10n/fi_FI.php index 9efc8e09cb..aa7fb394d4 100644 --- a/apps/files_external/l10n/fi_FI.php +++ b/apps/files_external/l10n/fi_FI.php @@ -6,11 +6,13 @@ $TRANSLATIONS = array( "Port (optional)" => "Portti (valinnainen)", "Region (optional)" => "Alue (valinnainen)", "Enable SSL" => "Käytä SSL:ää", -"URL" => "Verkko-osoite", +"Host" => "Isäntä", "Username" => "Käyttäjätunnus", "Password" => "Salasana", "Username (required)" => "Käyttäjätunnus (vaaditaan)", "Share" => "Jaa", +"URL" => "Verkko-osoite", +"Secure https://" => "Salattu https://", "Access granted" => "Pääsy sallittu", "Error configuring Dropbox storage" => "Virhe Dropbox levyn asetuksia tehtäessä", "Grant access" => "Salli pääsy", diff --git a/apps/files_external/l10n/fr.php b/apps/files_external/l10n/fr.php index c03a2f49e0..df2f63ec2e 100644 --- a/apps/files_external/l10n/fr.php +++ b/apps/files_external/l10n/fr.php @@ -4,11 +4,23 @@ $TRANSLATIONS = array( "Location" => "Emplacement", "Amazon S3" => "Amazon S3", "Key" => "Clé", +"Secret" => "Secret", "Access Key" => "Clé d'accès", -"URL" => "URL", +"Secret Key" => "Clé secrète", +"Hostname (optional)" => "Nom machine (optionnel)", +"Port (optional)" => "Port (optionnel)", +"Enable SSL" => "Activer SSL", +"App key" => "Clé App", +"Host" => "Hôte", "Username" => "Nom d'utilisateur", "Password" => "Mot de passe", +"Root" => "Root", +"Client ID" => "ID Client", +"Username (required)" => "Nom d'utilisation (requis)", +"API Key (required for Rackspace Cloud Files)" => "Clé API (requis pour Rackspace Cloud Files)", +"Password (required for OpenStack Object Storage)" => "Mot de passe (requis pour OpenStack Object Storage)", "Share" => "Partager", +"URL" => "URL", "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", diff --git a/apps/files_external/l10n/gl.php b/apps/files_external/l10n/gl.php index ccbdcce7f3..248afb5f6a 100644 --- a/apps/files_external/l10n/gl.php +++ b/apps/files_external/l10n/gl.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Activar o estilo de ruta", "App key" => "Clave da API", "App secret" => "Secreto do aplicativo", -"URL" => "URL", +"Host" => "Servidor", "Username" => "Nome de usuario", "Password" => "Contrasinal", "Root" => "Root (raíz)", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Compartir", "SMB / CIFS using OC login" => "SMB / CIFS usando acceso OC", "Username as share" => "Nome de usuario como compartición", +"URL" => "URL", "Secure https://" => "https:// seguro", "Remote subfolder" => "Subcartafol remoto", "Access granted" => "Concedeuse acceso", diff --git a/apps/files_external/l10n/he.php b/apps/files_external/l10n/he.php index 67cbb0cba2..f55a35fcad 100644 --- a/apps/files_external/l10n/he.php +++ b/apps/files_external/l10n/he.php @@ -1,10 +1,11 @@ "מיקום", -"URL" => "כתובת", +"Host" => "מארח", "Username" => "שם משתמש", "Password" => "סיסמא", "Share" => "שיתוף", +"URL" => "כתובת", "Access granted" => "הוענקה גישה", "Error configuring Dropbox storage" => "אירעה שגיאה בעת הגדרת אחסון ב־Dropbox", "Grant access" => "הענקת גישה", diff --git a/apps/files_external/l10n/hu_HU.php b/apps/files_external/l10n/hu_HU.php index 831bd69c23..d9c570d68c 100644 --- a/apps/files_external/l10n/hu_HU.php +++ b/apps/files_external/l10n/hu_HU.php @@ -1,10 +1,11 @@ "Hely", -"URL" => "URL", +"Host" => "Kiszolgáló", "Username" => "Felhasználónév", "Password" => "Jelszó", "Share" => "Megosztás", +"URL" => "URL", "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", diff --git a/apps/files_external/l10n/ia.php b/apps/files_external/l10n/ia.php index 844af213d8..978003e20c 100644 --- a/apps/files_external/l10n/ia.php +++ b/apps/files_external/l10n/ia.php @@ -1,10 +1,10 @@ "Loco", -"URL" => "URL", "Username" => "Nomine de usator", "Password" => "Contrasigno", "Share" => "Compartir", +"URL" => "URL", "Folder name" => "Nomine de dossier", "Groups" => "Gruppos", "Users" => "Usatores", diff --git a/apps/files_external/l10n/id.php b/apps/files_external/l10n/id.php index 4d33e6b450..a21ea7aef7 100644 --- a/apps/files_external/l10n/id.php +++ b/apps/files_external/l10n/id.php @@ -1,26 +1,44 @@ "Lokal", "Location" => "lokasi", -"URL" => "tautan", +"Amazon S3" => "Amazon S3", +"Hostname (optional)" => "Hostname (tambahan)", +"Port (optional)" => "Port (tambahan)", +"Region (optional)" => "Wilayah (tambahan)", +"Enable SSL" => "Aktifkan SSL", +"Host" => "Host", "Username" => "Nama Pengguna", "Password" => "Sandi", +"Root" => "Root", +"Username (required)" => "Nama pengguna (dibutuhkan)", "Share" => "Bagikan", +"URL" => "tautan", "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", +"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", +"Available for" => "Tersedia untuk", "Add storage" => "Tambahkan penyimpanan", +"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 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 39b750189d..daf9c4cb44 100644 --- a/apps/files_external/l10n/is.php +++ b/apps/files_external/l10n/is.php @@ -1,10 +1,11 @@ "Staðsetning", -"URL" => "URL", +"Host" => "Netþjónn", "Username" => "Notendanafn", "Password" => "Lykilorð", "Share" => "Deila", +"URL" => "URL", "Access granted" => "Aðgengi veitt", "Error configuring Dropbox storage" => "Villa við að setja upp Dropbox gagnasvæði", "Grant access" => "Veita aðgengi", diff --git a/apps/files_external/l10n/it.php b/apps/files_external/l10n/it.php index bc5b9d6dce..c6428a27ba 100644 --- a/apps/files_external/l10n/it.php +++ b/apps/files_external/l10n/it.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Abilita stile percorsi", "App key" => "Chiave applicazione", "App secret" => "Segreto applicazione", -"URL" => "URL", +"Host" => "Host", "Username" => "Nome utente", "Password" => "Password", "Root" => "Radice", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Condividi", "SMB / CIFS using OC login" => "SMB / CIFS utilizzando le credenziali di OC", "Username as share" => "Nome utente come condivisione", +"URL" => "URL", "Secure https://" => "Sicuro https://", "Remote subfolder" => "Sottocartella remota", "Access granted" => "Accesso consentito", diff --git a/apps/files_external/l10n/ja.php b/apps/files_external/l10n/ja.php index 4ac746caa0..b70dd2a09a 100644 --- a/apps/files_external/l10n/ja.php +++ b/apps/files_external/l10n/ja.php @@ -2,21 +2,60 @@ $TRANSLATIONS = array( "Local" => "ローカル", "Location" => "位置", -"URL" => "URL", +"Amazon S3" => "Amazon S3", +"Key" => "キー", +"Secret" => "シークレットキー", +"Bucket" => "バケット名", +"Amazon S3 and compliant" => "Amazon S3 と互換ストレージ", +"Access Key" => "アクセスキー", +"Secret Key" => "シークレットキー", +"Hostname (optional)" => "ホスト名 (オプション)", +"Port (optional)" => "ポート (オプション)", +"Region (optional)" => "リージョン (オプション)", +"Enable SSL" => "SSLを有効", +"Enable Path Style" => "パス形式を有効", +"App key" => "アプリキー", +"App secret" => "アプリシークレット", +"Host" => "ホスト", "Username" => "ユーザー名", "Password" => "パスワード", +"Root" => "ルート", +"Secure ftps://" => "Secure ftps://", +"Client ID" => "クライアントID", +"Client secret" => "クライアント秘密キー", +"OpenStack Object Storage" => "OpenStack Object Storage", +"Username (required)" => "ユーザー名 (必須)", +"Bucket (required)" => "バケット (必須)", +"Region (optional for OpenStack Object Storage)" => "リージョン (OpenStack Object Storage用のオプション)", +"API Key (required for Rackspace Cloud Files)" => "APIキー (Rackspace Cloud Filesに必須)", +"Tenantname (required for OpenStack Object Storage)" => "テナント名 (OpenStack Object Storage用に必要)", +"Password (required for OpenStack Object Storage)" => "パスワード (OpenStack Object Storage用に必要)", +"Service Name (required for OpenStack Object Storage)" => "サービス名 (OpenStack Object Storage用に必要)", +"URL of identity endpoint (required for OpenStack Object Storage)" => "識別用エンドポイントURL (OpenStack Object Storage用に必要)", +"Timeout of HTTP requests in seconds (optional)" => "HTTPリクエストのタイムアウト秒数 (オプション)", "Share" => "共有", +"SMB / CIFS using OC login" => "owncloudログインで SMB/CIFSを使用", +"Username as share" => "共有名", +"URL" => "URL", +"Secure https://" => "セキュア https://", +"Remote subfolder" => "リモートサブフォルダ", "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" => "保存されました", +"Note: " => "注意: ", +" 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." => "注意: PHPにcURLのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。", +"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." => "注意: PHPにFTPのエクステンションが入っていないか、有効ではありません。%s をマウントすることができません。このシステムの管理者にインストールをお願いしてください。", +"Note: \"%s\" is not installed. Mounting of %s is not possible. Please ask your system administrator to install it." => "注意: \"%s\" がインストールされていません。%sをマウントできません。このシステムの管理者にインストールをお願いしてください。", "External Storage" => "外部ストレージ", "Folder name" => "フォルダー名", "External storage" => "外部ストレージ", "Configuration" => "設定", "Options" => "オプション", +"Available for" => "以下が利用可能", "Add storage" => "ストレージを追加", "No user or group" => "ユーザーもしくはグループがありません", "All Users" => "すべてのユーザー", diff --git a/apps/files_external/l10n/ka_GE.php b/apps/files_external/l10n/ka_GE.php index f7eb01ba94..a87c8b4879 100644 --- a/apps/files_external/l10n/ka_GE.php +++ b/apps/files_external/l10n/ka_GE.php @@ -1,10 +1,11 @@ "ადგილმდებარეობა", -"URL" => "URL", +"Host" => "ჰოსტი", "Username" => "მომხმარებლის სახელი", "Password" => "პაროლი", "Share" => "გაზიარება", +"URL" => "URL", "Access granted" => "დაშვება მინიჭებულია", "Error configuring Dropbox storage" => "შეცდომა Dropbox საცავის კონფიგურირების დროს", "Grant access" => "დაშვების მინიჭება", diff --git a/apps/files_external/l10n/km.php b/apps/files_external/l10n/km.php index aac6337024..da17fac1bf 100644 --- a/apps/files_external/l10n/km.php +++ b/apps/files_external/l10n/km.php @@ -1,12 +1,22 @@ "ទីតាំង", -"URL" => "URL", +"Host" => "ម៉ាស៊ីន​ផ្ទុក", "Username" => "ឈ្មោះ​អ្នកប្រើ", "Password" => "ពាក្យសម្ងាត់", "Share" => "ចែក​រំលែក", +"URL" => "URL", +"Access granted" => "បាន​ទទួល​សិទ្ធិ​ចូល", +"Error configuring Dropbox storage" => "កំហុស​ការ​កំណត់​សណ្ឋាន​នៃ​ឃ្លាំងផ្ទុក Dropbox", +"Grant access" => "ទទួល​សិទ្ធិ​ចូល", +"Saved" => "បាន​រក្សាទុក", +"External Storage" => "ឃ្លាំងផ្ទុក​ខាងក្រៅ", "Folder name" => "ឈ្មោះ​ថត", +"External storage" => "ឃ្លាំងផ្ទុក​ខាងក្រៅ", +"Configuration" => "ការ​កំណត់​សណ្ឋាន", "Options" => "ជម្រើស", +"Add storage" => "បន្ថែម​ឃ្លាំងផ្ទុក", +"All Users" => "អ្នក​ប្រើ​ទាំងអស់", "Groups" => "ក្រុ", "Users" => "អ្នកប្រើ", "Delete" => "លុប" diff --git a/apps/files_external/l10n/ko.php b/apps/files_external/l10n/ko.php index 1df20b8072..631f95bc7b 100644 --- a/apps/files_external/l10n/ko.php +++ b/apps/files_external/l10n/ko.php @@ -1,15 +1,18 @@ "장소", -"URL" => "URL", +"Amazon S3" => "Amazon S3", +"Host" => "호스트", "Username" => "사용자 이름", "Password" => "암호", "Share" => "공유", +"URL" => "URL", "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" => "외부 저장소", diff --git a/apps/files_external/l10n/ku_IQ.php b/apps/files_external/l10n/ku_IQ.php index 72cc813352..3d5a3dd0d3 100644 --- a/apps/files_external/l10n/ku_IQ.php +++ b/apps/files_external/l10n/ku_IQ.php @@ -1,10 +1,10 @@ "شوێن", -"URL" => "ناونیشانی به‌سته‌ر", "Username" => "ناوی به‌کارهێنه‌ر", "Password" => "وشەی تێپەربو", "Share" => "هاوبەشی کردن", +"URL" => "ناونیشانی به‌سته‌ر", "Folder name" => "ناوی بوخچه", "Users" => "به‌كارهێنه‌ر" ); diff --git a/apps/files_external/l10n/lb.php b/apps/files_external/l10n/lb.php index 49517e7af3..233b3f8105 100644 --- a/apps/files_external/l10n/lb.php +++ b/apps/files_external/l10n/lb.php @@ -1,10 +1,11 @@ "Uert", -"URL" => "URL", +"Host" => "Host", "Username" => "Benotzernumm", "Password" => "Passwuert", "Share" => "Deelen", +"URL" => "URL", "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 736becc58d..908abcc748 100644 --- a/apps/files_external/l10n/lt_LT.php +++ b/apps/files_external/l10n/lt_LT.php @@ -1,10 +1,11 @@ "Vieta", -"URL" => "URL", +"Host" => "Mazgas", "Username" => "Prisijungimo vardas", "Password" => "Slaptažodis", "Share" => "Dalintis", +"URL" => "URL", "Access granted" => "Priėjimas suteiktas", "Error configuring Dropbox storage" => "Klaida nustatinėjant Dropbox talpyklą", "Grant access" => "Suteikti priėjimą", diff --git a/apps/files_external/l10n/lv.php b/apps/files_external/l10n/lv.php index 3506e55323..5234bda7dc 100644 --- a/apps/files_external/l10n/lv.php +++ b/apps/files_external/l10n/lv.php @@ -1,10 +1,11 @@ "Vieta", -"URL" => "URL", +"Host" => "Resursdators", "Username" => "Lietotājvārds", "Password" => "Parole", "Share" => "Dalīties", +"URL" => "URL", "Access granted" => "Piešķirta pieeja", "Error configuring Dropbox storage" => "Kļūda, konfigurējot Dropbox krātuvi", "Grant access" => "Piešķirt pieeju", diff --git a/apps/files_external/l10n/mk.php b/apps/files_external/l10n/mk.php index 0a72b65168..e1bf57d5b9 100644 --- a/apps/files_external/l10n/mk.php +++ b/apps/files_external/l10n/mk.php @@ -1,10 +1,11 @@ "Локација", -"URL" => "Адреса", +"Host" => "Домаќин", "Username" => "Корисничко име", "Password" => "Лозинка", "Share" => "Сподели", +"URL" => "Адреса", "Access granted" => "Пристапот е дозволен", "Error configuring Dropbox storage" => "Грешка при конфигурација на Dropbox", "Grant access" => "Дозволи пристап", diff --git a/apps/files_external/l10n/ms_MY.php b/apps/files_external/l10n/ms_MY.php index 789527e4a4..e19ec49978 100644 --- a/apps/files_external/l10n/ms_MY.php +++ b/apps/files_external/l10n/ms_MY.php @@ -1,10 +1,10 @@ "Lokasi", -"URL" => "URL", "Username" => "Nama pengguna", "Password" => "Kata laluan", "Share" => "Kongsi", +"URL" => "URL", "Groups" => "Kumpulan", "Users" => "Pengguna", "Delete" => "Padam" diff --git a/apps/files_external/l10n/nb_NO.php b/apps/files_external/l10n/nb_NO.php index f1f0a09fd5..7897f4b3f8 100644 --- a/apps/files_external/l10n/nb_NO.php +++ b/apps/files_external/l10n/nb_NO.php @@ -3,10 +3,11 @@ $TRANSLATIONS = array( "Local" => "Lokal", "Location" => "Sted", "Amazon S3" => "Amazon S3", -"URL" => "URL", +"Host" => "Tjener", "Username" => "Brukernavn", "Password" => "Passord", "Share" => "Del", +"URL" => "URL", "Access granted" => "Tilgang innvilget", "Error configuring Dropbox storage" => "Feil ved konfigurering av Dropbox-lagring", "Grant access" => "Gi tilgang", diff --git a/apps/files_external/l10n/nl.php b/apps/files_external/l10n/nl.php index 2e88c18740..2bdc047e96 100644 --- a/apps/files_external/l10n/nl.php +++ b/apps/files_external/l10n/nl.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Activeren pad stijl", "App key" => "App key", "App secret" => "App secret", -"URL" => "URL", +"Host" => "Host", "Username" => "Gebruikersnaam", "Password" => "Wachtwoord", "Root" => "Root", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Share", "SMB / CIFS using OC login" => "SMB / CIFS via OC inlog", "Username as share" => "Gebruikersnaam als share", +"URL" => "URL", "Secure https://" => "Secure https://", "Remote subfolder" => "Externe submap", "Access granted" => "Toegang toegestaan", diff --git a/apps/files_external/l10n/nn_NO.php b/apps/files_external/l10n/nn_NO.php index 542d3ec042..0ee80369ee 100644 --- a/apps/files_external/l10n/nn_NO.php +++ b/apps/files_external/l10n/nn_NO.php @@ -1,10 +1,11 @@ "Stad", -"URL" => "Nettstad", +"Host" => "Tenar", "Username" => "Brukarnamn", "Password" => "Passord", "Share" => "Del", +"URL" => "Nettstad", "Folder name" => "Mappenamn", "Configuration" => "Innstillingar", "Groups" => "Grupper", diff --git a/apps/files_external/l10n/oc.php b/apps/files_external/l10n/oc.php index e854c9f25a..bd5c98ca05 100644 --- a/apps/files_external/l10n/oc.php +++ b/apps/files_external/l10n/oc.php @@ -1,10 +1,10 @@ "Plaça", -"URL" => "URL", "Username" => "Non d'usancièr", "Password" => "Senhal", "Share" => "Parteja", +"URL" => "URL", "Groups" => "Grops", "Users" => "Usancièrs", "Delete" => "Escafa" diff --git a/apps/files_external/l10n/pl.php b/apps/files_external/l10n/pl.php index 9c13371b16..74d9347b60 100644 --- a/apps/files_external/l10n/pl.php +++ b/apps/files_external/l10n/pl.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Włącz styl ścieżki", "App key" => "Klucz aplikacji", "App secret" => "Hasło aplikacji", -"URL" => "URL", +"Host" => "Host", "Username" => "Nazwa użytkownika", "Password" => "Hasło", "Root" => "Root", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Udostępnij", "SMB / CIFS using OC login" => "SMB / CIFS przy użyciu loginu OC", "Username as share" => "Użytkownik jako zasób", +"URL" => "URL", "Secure https://" => "Bezpieczny https://", "Remote subfolder" => "Zdalny podfolder", "Access granted" => "Dostęp do", diff --git a/apps/files_external/l10n/pt_BR.php b/apps/files_external/l10n/pt_BR.php index d9544ae159..b027a92e50 100644 --- a/apps/files_external/l10n/pt_BR.php +++ b/apps/files_external/l10n/pt_BR.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Habilitar Estilo do Caminho", "App key" => "Chave do Aplicativo", "App secret" => "Segredo da Aplicação", -"URL" => "URL", +"Host" => "Servidor", "Username" => "Nome de Usuário", "Password" => "Senha", "Root" => "Raiz", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Compartilhar", "SMB / CIFS using OC login" => "SMB / CIFS usando OC logon", "Username as share" => "Nome de usuário como compartilhado", +"URL" => "URL", "Secure https://" => "https:// segura", "Remote subfolder" => "Subpasta remota", "Access granted" => "Acesso concedido", diff --git a/apps/files_external/l10n/pt_PT.php b/apps/files_external/l10n/pt_PT.php index 767ddeec8a..2daa72715b 100644 --- a/apps/files_external/l10n/pt_PT.php +++ b/apps/files_external/l10n/pt_PT.php @@ -12,7 +12,7 @@ $TRANSLATIONS = array( "Enable SSL" => "Activar SSL", "App key" => "Chave da aplicação", "App secret" => "Chave secreta da aplicação", -"URL" => "URL", +"Host" => "Endereço", "Username" => "Nome de utilizador", "Password" => "Palavra-passe", "Root" => "Raiz", @@ -20,6 +20,7 @@ $TRANSLATIONS = array( "Client secret" => "Segredo do cliente", "Username (required)" => "Utilizador (requerido)", "Share" => "Partilhar", +"URL" => "URL", "Remote subfolder" => "Sub-pasta remota ", "Access granted" => "Acesso autorizado", "Error configuring Dropbox storage" => "Erro ao configurar o armazenamento do Dropbox", diff --git a/apps/files_external/l10n/ro.php b/apps/files_external/l10n/ro.php index cc48e20ab0..d5e1e90c54 100644 --- a/apps/files_external/l10n/ro.php +++ b/apps/files_external/l10n/ro.php @@ -1,10 +1,11 @@ "Locație", -"URL" => "URL", +"Host" => "Gazdă", "Username" => "Nume utilizator", "Password" => "Parolă", "Share" => "Partajează", +"URL" => "URL", "Access granted" => "Acces permis", "Error configuring Dropbox storage" => "Eroare la configurarea mediului de stocare Dropbox", "Grant access" => "Permite accesul", diff --git a/apps/files_external/l10n/ru.php b/apps/files_external/l10n/ru.php index be1307a9e6..6aded8e9a3 100644 --- a/apps/files_external/l10n/ru.php +++ b/apps/files_external/l10n/ru.php @@ -1,10 +1,12 @@ "Локально", "Location" => "Местоположение", -"URL" => "Ссылка", +"Host" => "Сервер", "Username" => "Имя пользователя", "Password" => "Пароль", "Share" => "Открыть доступ", +"URL" => "Ссылка", "Access granted" => "Доступ предоставлен", "Error configuring Dropbox storage" => "Ошибка при настройке хранилища Dropbox", "Grant access" => "Предоставление доступа", diff --git a/apps/files_external/l10n/si_LK.php b/apps/files_external/l10n/si_LK.php index 908f82d8ee..960ededaa6 100644 --- a/apps/files_external/l10n/si_LK.php +++ b/apps/files_external/l10n/si_LK.php @@ -1,10 +1,11 @@ "ස්ථානය", -"URL" => "URL", +"Host" => "සත්කාරකය", "Username" => "පරිශීලක නම", "Password" => "මුර පදය", "Share" => "බෙදා හදා ගන්න", +"URL" => "URL", "Access granted" => "පිවිසීමට හැක", "Error configuring Dropbox storage" => "Dropbox ගබඩාව වින්‍යාස කිරීමේ දෝශයක් ඇත", "Grant access" => "පිවිසුම ලබාදෙන්න", diff --git a/apps/files_external/l10n/sk_SK.php b/apps/files_external/l10n/sk_SK.php index e30b007c3c..f576d92cda 100644 --- a/apps/files_external/l10n/sk_SK.php +++ b/apps/files_external/l10n/sk_SK.php @@ -2,10 +2,11 @@ $TRANSLATIONS = array( "Local" => "Lokálny", "Location" => "Umiestnenie", -"URL" => "URL", +"Host" => "Hostiteľ", "Username" => "Používateľské meno", "Password" => "Heslo", "Share" => "Zdieľať", +"URL" => "URL", "Access granted" => "Prístup povolený", "Error configuring Dropbox storage" => "Chyba pri konfigurácii úložiska Dropbox", "Grant access" => "Povoliť prístup", diff --git a/apps/files_external/l10n/sl.php b/apps/files_external/l10n/sl.php index 04fa28127a..c47e962b6e 100644 --- a/apps/files_external/l10n/sl.php +++ b/apps/files_external/l10n/sl.php @@ -2,10 +2,33 @@ $TRANSLATIONS = array( "Local" => "Krajevno", "Location" => "Mesto", -"URL" => "Naslov URL", +"Amazon S3" => "Amazon S3", +"Key" => "Ključ", +"Secret" => "Skrivni ključ", +"Amazon S3 and compliant" => "Amazon S3 in podobno", +"Access Key" => "Ključ za dostop", +"Secret Key" => "Skrivni ključ", +"Hostname (optional)" => "Ime gostitelja (izbirno)", +"Port (optional)" => "Vrata (izbirno)", +"Region (optional)" => "Območje (izbirno)", +"Enable SSL" => "Omogoči SSL", +"Enable Path Style" => "Omogoči slog poti", +"App key" => "Programski ključ", +"App secret" => "Skrivni programski ključ", +"Host" => "Gostitelj", "Username" => "Uporabniško ime", "Password" => "Geslo", +"Root" => "Koren", +"Secure ftps://" => "Varni način ftps://", +"Client ID" => "ID odjemalca", +"Client secret" => "Skrivni ključ odjemalca", +"Username (required)" => "Uporabniško ime (zahtevano)", "Share" => "Souporaba", +"SMB / CIFS using OC login" => "SMB / CIFS z uporabo prijave OC", +"Username as share" => "Uporabniško ime za souporabo", +"URL" => "Naslov URL", +"Secure https://" => "Varni način https://", +"Remote subfolder" => "Oddaljena podrejena mapa", "Access granted" => "Dostop je odobren", "Error configuring Dropbox storage" => "Napaka nastavljanja shrambe Dropbox", "Grant access" => "Odobri dostop", diff --git a/apps/files_external/l10n/sq.php b/apps/files_external/l10n/sq.php index 563a1b7dd9..1904514fdc 100644 --- a/apps/files_external/l10n/sq.php +++ b/apps/files_external/l10n/sq.php @@ -1,10 +1,11 @@ "Vendndodhja", -"URL" => "URL-i", +"Host" => "Pritësi", "Username" => "Përdoruesi", "Password" => "fjalëkalim", "Share" => "Ndaj", +"URL" => "URL-i", "Groups" => "Grupet", "Users" => "Përdoruesit", "Delete" => "Elimino" diff --git a/apps/files_external/l10n/sr.php b/apps/files_external/l10n/sr.php index b0276764a8..bf150f5b5b 100644 --- a/apps/files_external/l10n/sr.php +++ b/apps/files_external/l10n/sr.php @@ -1,6 +1,7 @@ "Локација", +"Host" => "Домаћин", "Username" => "Корисничко име", "Password" => "Лозинка", "Share" => "Дели", diff --git a/apps/files_external/l10n/sv.php b/apps/files_external/l10n/sv.php index a15ea0ed16..a1c2a7cabe 100644 --- a/apps/files_external/l10n/sv.php +++ b/apps/files_external/l10n/sv.php @@ -2,10 +2,18 @@ $TRANSLATIONS = array( "Local" => "Lokal", "Location" => "Plats", -"URL" => "URL", +"Amazon S3" => "Amazon S3", +"Key" => "Nyckel", +"Secret" => "Hemlig", +"Enable SSL" => "Aktivera SSL", +"Host" => "Server", "Username" => "Användarnamn", "Password" => "Lösenord", +"Root" => "Root", +"Secure ftps://" => "Säker ftps://", "Share" => "Dela", +"URL" => "URL", +"Secure https://" => "Säker https://", "Access granted" => "Åtkomst beviljad", "Error configuring Dropbox storage" => "Fel vid konfigurering av Dropbox", "Grant access" => "Bevilja åtkomst", diff --git a/apps/files_external/l10n/ta_LK.php b/apps/files_external/l10n/ta_LK.php index 066cf411dd..a94b7417ff 100644 --- a/apps/files_external/l10n/ta_LK.php +++ b/apps/files_external/l10n/ta_LK.php @@ -1,10 +1,11 @@ "இடம்", -"URL" => "URL", +"Host" => "ஓம்புனர்", "Username" => "பயனாளர் பெயர்", "Password" => "கடவுச்சொல்", "Share" => "பகிர்வு", +"URL" => "URL", "Access granted" => "அனுமதி வழங்கப்பட்டது", "Error configuring Dropbox storage" => "Dropbox சேமிப்பை தகவமைப்பதில் வழு", "Grant access" => "அனுமதியை வழங்கல்", diff --git a/apps/files_external/l10n/th_TH.php b/apps/files_external/l10n/th_TH.php index 3edf8c6382..9f393a2546 100644 --- a/apps/files_external/l10n/th_TH.php +++ b/apps/files_external/l10n/th_TH.php @@ -1,10 +1,11 @@ "ตำแหน่งที่อยู่", -"URL" => "URL", +"Host" => "โฮสต์", "Username" => "ชื่อผู้ใช้งาน", "Password" => "รหัสผ่าน", "Share" => "แชร์", +"URL" => "URL", "Access granted" => "การเข้าถึงได้รับอนุญาตแล้ว", "Error configuring Dropbox storage" => "เกิดข้อผิดพลาดในการกำหนดค่าพื้นที่จัดเก็บข้อมูล Dropbox", "Grant access" => "อนุญาตให้เข้าถึงได้", diff --git a/apps/files_external/l10n/tr.php b/apps/files_external/l10n/tr.php index aa3290bd4b..5af8813e67 100644 --- a/apps/files_external/l10n/tr.php +++ b/apps/files_external/l10n/tr.php @@ -16,7 +16,7 @@ $TRANSLATIONS = array( "Enable Path Style" => "Yol Biçemini Etkinleştir", "App key" => "Uyg. anahtarı", "App secret" => "Uyg. parolası", -"URL" => "URL", +"Host" => "Sunucu", "Username" => "Kullanıcı Adı:", "Password" => "Parola:", "Root" => "Kök", @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Share" => "Paylaş", "SMB / CIFS using OC login" => "OC oturumu kullanarak SMB / CIFS", "Username as share" => "Paylaşım olarak kullanıcı adı", +"URL" => "URL", "Secure https://" => "Güvenli https://", "Remote subfolder" => "Uzak alt klasör", "Access granted" => "Giriş kabul edildi", diff --git a/apps/files_external/l10n/ug.php b/apps/files_external/l10n/ug.php index bd7dc42986..701a5457ae 100644 --- a/apps/files_external/l10n/ug.php +++ b/apps/files_external/l10n/ug.php @@ -1,10 +1,11 @@ "ئورنى", -"URL" => "URL", +"Host" => "باش ئاپپارات", "Username" => "ئىشلەتكۈچى ئاتى", "Password" => "ئىم", "Share" => "ھەمبەھىر", +"URL" => "URL", "Folder name" => "قىسقۇچ ئاتى", "External storage" => "سىرتقى ساقلىغۇچ", "Configuration" => "سەپلىمە", diff --git a/apps/files_external/l10n/uk.php b/apps/files_external/l10n/uk.php index f644fe8606..aea352a686 100644 --- a/apps/files_external/l10n/uk.php +++ b/apps/files_external/l10n/uk.php @@ -1,10 +1,11 @@ "Місце", -"URL" => "URL", +"Host" => "Хост", "Username" => "Ім'я користувача", "Password" => "Пароль", "Share" => "Поділитися", +"URL" => "URL", "Access granted" => "Доступ дозволено", "Error configuring Dropbox storage" => "Помилка при налаштуванні сховища Dropbox", "Grant access" => "Дозволити доступ", diff --git a/apps/files_external/l10n/ur_PK.php b/apps/files_external/l10n/ur_PK.php index e2138b9046..5d4695b511 100644 --- a/apps/files_external/l10n/ur_PK.php +++ b/apps/files_external/l10n/ur_PK.php @@ -1,7 +1,11 @@ "مقام", "Username" => "یوزر نیم", "Password" => "پاسورڈ", -"Users" => "یوزرز" +"Share" => "تقسیم", +"URL" => "یو ار ایل", +"Users" => "یوزرز", +"Delete" => "حذف کریں" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_external/l10n/vi.php b/apps/files_external/l10n/vi.php index 86d1236f66..03d50bc143 100644 --- a/apps/files_external/l10n/vi.php +++ b/apps/files_external/l10n/vi.php @@ -1,10 +1,11 @@ "Vị trí", -"URL" => "URL", +"Host" => "Máy chủ", "Username" => "Tên đăng nhập", "Password" => "Mật khẩu", "Share" => "Chia sẻ", +"URL" => "URL", "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", diff --git a/apps/files_external/l10n/zh_CN.php b/apps/files_external/l10n/zh_CN.php index a61331de36..95e9c0e643 100644 --- a/apps/files_external/l10n/zh_CN.php +++ b/apps/files_external/l10n/zh_CN.php @@ -1,26 +1,45 @@ "本地", "Location" => "地点", -"URL" => "URL", +"Amazon S3" => "Amazon S3", +"Access Key" => "访问密钥", +"Hostname (optional)" => "域名 (可选)", +"Port (optional)" => "端口 (可选)", +"Region (optional)" => "区域 (optional)", +"Enable SSL" => "启用 SSL", +"Host" => "主机", "Username" => "用户名", "Password" => "密码", +"Root" => "根路径", +"Secure ftps://" => "安全 ftps://", "Share" => "共享", +"SMB / CIFS using OC login" => "SMB / CIFS 使用 OC 登录信息", +"URL" => "URL", +"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存储时出错", +"Saved" => "已保存", +"Note: " => "注意:", +" and " => "和", "External Storage" => "外部存储", "Folder name" => "目录名称", "External storage" => "外部存储", "Configuration" => "配置", "Options" => "选项", +"Available for" => "可用于", "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" => "导入根证书" ); diff --git a/apps/files_external/l10n/zh_HK.php b/apps/files_external/l10n/zh_HK.php index b3a22c91bb..5a15446948 100644 --- a/apps/files_external/l10n/zh_HK.php +++ b/apps/files_external/l10n/zh_HK.php @@ -1,9 +1,9 @@ "網址", "Username" => "用戶名稱", "Password" => "密碼", "Share" => "分享", +"URL" => "網址", "Folder name" => "資料夾名稱", "Groups" => "群組", "Users" => "用戶", diff --git a/apps/files_external/l10n/zh_TW.php b/apps/files_external/l10n/zh_TW.php index a4b0ebe4dd..154009f7a1 100644 --- a/apps/files_external/l10n/zh_TW.php +++ b/apps/files_external/l10n/zh_TW.php @@ -2,10 +2,11 @@ $TRANSLATIONS = array( "Local" => "本地", "Location" => "地點", -"URL" => "URL", +"Host" => "主機", "Username" => "使用者名稱:", "Password" => "密碼", "Share" => "分享", +"URL" => "URL", "Access granted" => "允許存取", "Error configuring Dropbox storage" => "設定 Dropbox 儲存時發生錯誤", "Grant access" => "允許存取", diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 2093fb7e58..7ff17f0e98 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -25,7 +25,7 @@ namespace OC\Files\Storage; set_include_path(get_include_path() . PATH_SEPARATOR . - \OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php'); + \OC_App::getAppPath('files_external') . '/3rdparty/aws-sdk-php'); require 'aws-autoloader.php'; use Aws\S3\S3Client; diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 99eca2f38c..7a651239cb 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -132,7 +132,7 @@ class OC_Mount_Config { } // Load system mount points - $mountConfig = self::readData(false); + $mountConfig = self::readData(); if (isset($mountConfig[self::MOUNT_TYPE_GLOBAL])) { foreach ($mountConfig[self::MOUNT_TYPE_GLOBAL] as $mountPoint => $options) { $options['options'] = self::decryptPasswords($options['options']); @@ -169,7 +169,7 @@ class OC_Mount_Config { } // Load personal mount points - $mountConfig = self::readData(true); + $mountConfig = self::readData($user); if (isset($mountConfig[self::MOUNT_TYPE_USER][$user])) { foreach ($mountConfig[self::MOUNT_TYPE_USER][$user] as $mountPoint => $options) { $options['options'] = self::decryptPasswords($options['options']); @@ -233,7 +233,7 @@ class OC_Mount_Config { * @return array */ public static function getSystemMountPoints() { - $mountPoints = self::readData(false); + $mountPoints = self::readData(); $backends = self::getBackends(); $system = array(); if (isset($mountPoints[self::MOUNT_TYPE_GROUP])) { @@ -306,7 +306,7 @@ class OC_Mount_Config { * @return array */ public static function getPersonalMountPoints() { - $mountPoints = self::readData(true); + $mountPoints = self::readData(OCP\User::getUser()); $backEnds = self::getBackends(); $uid = OCP\User::getUser(); $personal = array(); @@ -359,10 +359,10 @@ class OC_Mount_Config { * Add a mount point to the filesystem * @param string $mountPoint Mount point * @param string $class Backend class - * @param array Backend parameters for the class + * @param array $classOptions Backend parameters for the class * @param string $mountType MOUNT_TYPE_GROUP | MOUNT_TYPE_USER * @param string $applicable User or group to apply mount to - * @param bool Personal or system mount point i.e. is this being called from the personal or admin page + * @param bool $isPersonal Personal or system mount point i.e. is this being called from the personal or admin page * @return boolean */ public static function addMountPoint($mountPoint, @@ -400,28 +400,20 @@ class OC_Mount_Config { 'options' => self::encryptPasswords($classOptions)) ) ); - $mountPoints = self::readData($isPersonal); - // Merge the new mount point into the current mount points - if (isset($mountPoints[$mountType])) { - if (isset($mountPoints[$mountType][$applicable])) { - $mountPoints[$mountType][$applicable] - = array_merge($mountPoints[$mountType][$applicable], $mount[$applicable]); - } else { - $mountPoints[$mountType] = array_merge($mountPoints[$mountType], $mount); - } - } else { - $mountPoints[$mountType] = $mount; - } - self::writeData($isPersonal, $mountPoints); + + $mountPoints = self::readData($isPersonal ? OCP\User::getUser() : NULL); + $mountPoints = self::mergeMountPoints($mountPoints, $mount, $mountType); + self::writeData($isPersonal ? OCP\User::getUser() : NULL, $mountPoints); + return self::getBackendStatus($class, $classOptions, $isPersonal); } /** * - * @param string Mount point - * @param string MOUNT_TYPE_GROUP | MOUNT_TYPE_USER - * @param string User or group to remove mount from - * @param bool Personal or system mount point + * @param string $mountPoint Mount point + * @param string $mountType MOUNT_TYPE_GROUP | MOUNT_TYPE_USER + * @param string $applicable User or group to remove mount from + * @param bool $isPersonal Personal or system mount point * @return bool */ public static function removeMountPoint($mountPoint, $mountType, $applicable, $isPersonal = false) { @@ -434,7 +426,7 @@ class OC_Mount_Config { } else { $mountPoint = '/$user/files/'.ltrim($mountPoint, '/'); } - $mountPoints = self::readData($isPersonal); + $mountPoints = self::readData($isPersonal ? OCP\User::getUser() : NULL); // Remove mount point unset($mountPoints[$mountType][$applicable][$mountPoint]); // Unset parent arrays if empty @@ -444,20 +436,20 @@ class OC_Mount_Config { unset($mountPoints[$mountType]); } } - self::writeData($isPersonal, $mountPoints); + self::writeData($isPersonal ? OCP\User::getUser() : NULL, $mountPoints); return true; } /** * Read the mount points in the config file into an array - * @param boolean $isPersonal Personal or system config file + * @param string|null $user If not null, personal for $user, otherwise system * @return array */ - private static function readData($isPersonal) { + private static function readData($user = NULL) { $parser = new \OC\ArrayParser(); - if ($isPersonal) { - $phpFile = OC_User::getHome(OCP\User::getUser()).'/mount.php'; - $jsonFile = OC_User::getHome(OCP\User::getUser()).'/mount.json'; + if (isset($user)) { + $phpFile = OC_User::getHome($user).'/mount.php'; + $jsonFile = OC_User::getHome($user).'/mount.json'; } else { $phpFile = OC::$SERVERROOT.'/config/mount.php'; $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/'); @@ -479,13 +471,12 @@ class OC_Mount_Config { /** * Write the mount points to the config file - * @param bool Personal or system config file - * @param array Mount points - * @param boolean $isPersonal + * @param string|null $user If not null, personal for $user, otherwise system + * @param array $data Mount points */ - private static function writeData($isPersonal, $data) { - if ($isPersonal) { - $file = OC_User::getHome(OCP\User::getUser()).'/mount.json'; + private static function writeData($user, $data) { + if (isset($user)) { + $file = OC_User::getHome($user).'/mount.json'; } else { $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/'); $file = \OC_Config::getValue('mount_file', $datadir . '/mount.json'); @@ -619,9 +610,9 @@ class OC_Mount_Config { /** * Returns a dependency missing message - * @param $l OC_L10N - * @param $module string - * @param $backend string + * @param OC_L10N $l + * @param string $module + * @param string $backend * @return string */ private static function getSingleDependencyMessage($l, $module, $backend) { @@ -667,7 +658,7 @@ class OC_Mount_Config { /** * Encrypt a single password * @param string $password plain text password - * @return encrypted password + * @return string encrypted password */ private static function encryptPassword($password) { $cipher = self::getCipher(); @@ -679,7 +670,7 @@ class OC_Mount_Config { /** * Decrypts a single password * @param string $encryptedPassword encrypted password - * @return plain text password + * @return string plain text password */ private static function decryptPassword($encryptedPassword) { $cipher = self::getCipher(); @@ -690,6 +681,28 @@ class OC_Mount_Config { return $cipher->decrypt($binaryPassword); } + /** + * Merges mount points + * @param array $data Existing mount points + * @param array $mountPoint New mount point + * @param string $mountType + * @return array + */ + private static function mergeMountPoints($data, $mountPoint, $mountType) { + $applicable = key($mountPoint); + if (isset($data[$mountType])) { + if (isset($data[$mountType][$applicable])) { + $data[$mountType][$applicable] + = array_merge($data[$mountType][$applicable], $mountPoint[$applicable]); + } else { + $data[$mountType] = array_merge($data[$mountType], $mountPoint); + } + } else { + $data[$mountType] = $mountPoint; + } + return $data; + } + /** * Returns the encryption cipher */ diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 38de3360f2..0b624b2717 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -63,10 +63,10 @@ class Dropbox extends \OC\Files\Storage\Common { } /** - * @brief Returns the path's metadata + * Returns the path's metadata * @param string $path path for which to return the metadata - * @param $list if true, also return the directory's contents - * @return directory contents if $list is true, file metadata if $list is + * @param bool $list if true, also return the directory's contents + * @return mixed directory contents if $list is true, file metadata if $list is * false, null if the file doesn't exist or "false" if the operation failed */ private function getMetaData($path, $list = false) { diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php index b3f8b1444a..2650a94f85 100644 --- a/apps/files_external/lib/ftp.php +++ b/apps/files_external/lib/ftp.php @@ -64,7 +64,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ /** * Unlinks file or directory - * @param string @path + * @param string $path */ public function unlink($path) { if ($this->is_dir($path)) { diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index b1d355323d..6e53c4a993 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -83,7 +83,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ /** * Unlinks file or directory - * @param string @path + * @param string $path */ public function unlink($path) { if ($this->is_dir($path)) { diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index a202d3843c..03364867b0 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -23,7 +23,7 @@ namespace OC\Files\Storage; set_include_path(get_include_path() . PATH_SEPARATOR . - \OC_App::getAppPath('files_external') . '/3rdparty/php-opencloud/lib'); + \OC_App::getAppPath('files_external') . '/3rdparty/php-opencloud/lib'); require_once 'openstack.php'; use \OpenCloud; @@ -31,25 +31,25 @@ use \OpenCloud\Common\Exceptions; class Swift extends \OC\Files\Storage\Common { - /** - * @var \OpenCloud\ObjectStore - */ + /** + * @var \OpenCloud\ObjectStore + */ private $connection; - /** - * @var \OpenCloud\ObjectStore\Container - */ + /** + * @var \OpenCloud\ObjectStore\Container + */ private $container; - /** - * @var \OpenCloud\OpenStack - */ + /** + * @var \OpenCloud\OpenStack + */ private $anchor; - /** - * @var string - */ + /** + * @var string + */ private $bucket; - /** - * @var array - */ + /** + * @var array + */ private static $tmpFiles = array(); /** 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 index 81a31e14c6..650299075e 100644 --- a/apps/files_external/tests/dynamicmountconfig.php +++ b/apps/files_external/tests/dynamicmountconfig.php @@ -22,8 +22,6 @@ require_once __DIR__ . '/../../../lib/base.php'; -require __DIR__ . '/../lib/config.php'; - /** * Class Test_Mount_Config_Dummy_Backend */ diff --git a/apps/files_external/tests/mountconfig.php b/apps/files_external/tests/mountconfig.php index 1921ec76af..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; diff --git a/apps/files_sharing/ajax/list.php b/apps/files_sharing/ajax/list.php index c31b3a0e06..93964c5ed5 100644 --- a/apps/files_sharing/ajax/list.php +++ b/apps/files_sharing/ajax/list.php @@ -40,6 +40,9 @@ if (isset($_GET['dir'])) { $relativePath = $_GET['dir']; } +$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name'; +$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false; + $data = \OCA\Files_Sharing\Helper::setupFromToken($token, $relativePath, $password); $linkItem = $data['linkItem']; @@ -56,7 +59,7 @@ if (!\OC\Files\Filesystem::is_dir($dir . '/')) { $data = array(); // make filelist -$files = \OCA\Files\Helper::getFiles($dir); +$files = \OCA\Files\Helper::getFiles($dir, $sortAttribute, $sortDirection); $formattedFiles = array(); foreach ($files as $file) { @@ -80,4 +83,4 @@ if (OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes') === 'n $data['permissions'] = $permissions; -OCP\JSON::success(array('data' => $data)); \ No newline at end of file +OCP\JSON::success(array('data' => $data)); diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php index 6ba47e5b3a..0b2af7a6e5 100644 --- a/apps/files_sharing/ajax/publicpreview.php +++ b/apps/files_sharing/ajax/publicpreview.php @@ -15,6 +15,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(\OC_Response::STATUS_BAD_REQUEST); @@ -69,6 +70,10 @@ if(substr($path, 0, 1) === '/') { $path = substr($path, 1); } +if ($keepAspect === true) { + $maxY = $maxX; +} + if($maxX === 0 || $maxY === 0) { \OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST); \OC_Log::write('core-preview', 'x and/or y set to 0', \OC_Log::DEBUG); @@ -83,8 +88,9 @@ try{ $preview->setMaxX($maxX); $preview->setMaxY($maxY); $preview->setScalingUp($scalingUp); + $preview->setKeepAspect($keepAspect); - $preview->show(); + $preview->showPreview(); } catch (\Exception $e) { \OC_Response::setStatus(\OC_Response::STATUS_INTERNAL_SERVER_ERROR); \OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG); diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php index 06e454b7d7..7c2834dc9c 100644 --- a/apps/files_sharing/appinfo/routes.php +++ b/apps/files_sharing/appinfo/routes.php @@ -1,9 +1,9 @@ create('core_ajax_public_preview', '/publicpreview.png')->action( -function() { - require_once __DIR__ . '/../ajax/publicpreview.php'; -}); +$this->create('core_ajax_public_preview', '/publicpreview')->action( + function() { + require_once __DIR__ . '/../ajax/publicpreview.php'; + }); // OCS API diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css index 67d8470194..70897af9eb 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -1,7 +1,3 @@ -#controls { - left: 0; -} - #preview { background: #fff; text-align: center; diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index ae2412f6a3..d3d4479215 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -8,77 +8,164 @@ * */ -/* global OC, FileActions, FileList, Files */ +/* global FileActions, Files */ +/* global dragOptions, folderDropOptions */ +OCA.Sharing = {}; +if (!OCA.Files) { + OCA.Files = {}; +} +OCA.Sharing.PublicApp = { + _initialized: false, -$(document).ready(function() { + initialize: function($el) { + if (this._initialized) { + return; + } + this._initialized = true; + // file list mode ? + if ($el.find('#filestable')) { + this.fileList = new OCA.Files.FileList( + $el, + { + scrollContainer: $(window), + dragOptions: dragOptions, + folderDropOptions: folderDropOptions + } + ); + this.files = OCA.Files.Files; + this.files.initialize(); + } - 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) { - // Trigger default action if not download TODO - var action = FileActions.getDefault(mimetype, 'file', OC.PERMISSION_READ); - if (typeof action !== 'undefined') { - action($('#filename').val()); + + if (typeof FileActions !== 'undefined') { + // Show file preview if previewer is available, images are already handled by the template + 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()); + } } } + + // 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'); + } + + if (this.fileList) { + // TODO: move this to a separate PublicFileList class that extends OCA.Files.FileList (+ unit tests) + this.fileList.getDownloadUrl = function(filename, dir) { + if ($.isArray(filename)) { + filename = JSON.stringify(filename); + } + var path = dir || FileList.getCurrentDirectory(); + var params = { + service: 'files', + t: $('#sharingToken').val(), + path: path, + files: filename, + download: null + }; + return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); + }; + + this.fileList.getAjaxUrl = function(action, params) { + params = params || {}; + params.t = $('#sharingToken').val(); + return OC.filePath('files_sharing', 'ajax', action + '.php') + '?' + OC.buildQueryString(params); + }; + + this.fileList.linkTo = function(dir) { + var params = { + service: 'files', + t: $('#sharingToken').val(), + dir: dir + }; + return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); + }; + + this.fileList.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 + }; + }); + + this.fileActions = _.extend({}, OCA.Files.FileActions); + this.fileActions.registerDefaultActions(this.fileList); + delete this.fileActions.actions.all.Share; + this.fileList.setFileActions(this.fileActions); + + this.fileList.changeDirectory($('#dir').val() || '/', false, true); + + // URL history handling + this.fileList.$el.on('changeDirectory', _.bind(this._onDirectoryChanged, this)); + OC.Util.History.addOnPopStateHandler(_.bind(this._onUrlChanged, this)); + } + + $(document).on('click', '#directLink', function() { + $(this).focus(); + $(this).select(); + }); + + // legacy + window.FileList = this.fileList; + }, + + _onDirectoryChanged: function(e) { + OC.Util.History.pushState({ + service: 'files', + t: $('#sharingToken').val(), + // arghhhh, why is this not called "dir" !? + path: e.dir + }); + }, + + _onUrlChanged: function(params) { + this.fileList.changeDirectory(params.path || params.dir, false, true); } +}; - // override since the format is different - Files.getDownloadUrl = function(filename, dir) { - if ($.isArray(filename)) { - filename = JSON.stringify(filename); - } - var path = dir || FileList.getCurrentDirectory(); - var params = { - service: 'files', - t: $('#sharingToken').val(), +$(document).ready(function() { + var App = OCA.Sharing.PublicApp; + App.initialize($('#preview')); + + // HACK: for oc-dialogs previews that depends on Files: + Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { + return App.fileList.lazyLoadPreview({ path: path, - files: filename, - download: null - }; - return OC.filePath('', '', 'public.php') + '?' + OC.buildQueryString(params); + mime: mime, + callback: ready, + width: width, + height: height, + etag: etag + }); }; - - 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(); - $(this).select(); - }); - }); + diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 3c7c9239a6..973c63c5d7 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -8,15 +8,15 @@ * */ -/* global OC, t, FileList, FileActions */ +/* global FileList, FileActions */ $(document).ready(function() { - var disableSharing = $('#disableSharing').data('status'), - sharesLoaded = false; + var sharesLoaded = false; - if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !disableSharing) { - var oldCreateRow = FileList._createRow; - FileList._createRow = function(fileData) { + if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined') { + // TODO: make a separate class for this or a hook or jQuery event ? + var oldCreateRow = OCA.Files.FileList.prototype._createRow; + OCA.Files.FileList.prototype._createRow = function(fileData) { var tr = oldCreateRow.apply(this, arguments); if (fileData.shareOwner) { tr.attr('data-share-owner', fileData.shareOwner); @@ -25,14 +25,16 @@ $(document).ready(function() { }; $('#fileList').on('fileActionsReady',function(){ - - var allShared = $('#fileList').find('[data-share-owner] [data-Action="Share"]'); + var $fileList = $(this); + 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}); }); + // FIXME: these calls are also working on hard-coded + // list selectors... if (!sharesLoaded){ OC.Share.loadIcons('file'); // assume that we got all shares, so switching directories diff --git a/apps/files_sharing/l10n/ast.php b/apps/files_sharing/l10n/ast.php index d90df88723..fa3704ea6b 100644 --- a/apps/files_sharing/l10n/ast.php +++ b/apps/files_sharing/l10n/ast.php @@ -1,7 +1,17 @@ "Compartíu por {owner}", +"This share is password-protected" => "Esta compartición tien contraseña protexida", +"The password is wrong. Try again." => "La contraseña ye incorreuta. Inténtalo otra vegada.", "Password" => "Contraseña", -"Download" => "Baxar" +"Sorry, this link doesn’t seem to work anymore." => "Sentímoslo, esti enllaz paez que yá nun furrula.", +"Reasons might be:" => "Les razones pueden ser: ", +"the item was removed" => "desanicióse l'elementu", +"the link expired" => "l'enllaz caducó", +"sharing is disabled" => "compartir ta desactiváu", +"For more info, please ask the person who sent this link." => "Pa más información, entrúga-y a la persona qu'unvió esti enllaz", +"Download" => "Baxar", +"Download %s" => "Descargar %s", +"Direct link" => "Enllaz direutu" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/eu.php b/apps/files_sharing/l10n/eu.php index 03c2f844a1..8be7bcb2a4 100644 --- a/apps/files_sharing/l10n/eu.php +++ b/apps/files_sharing/l10n/eu.php @@ -11,6 +11,7 @@ $TRANSLATIONS = array( "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", "Download" => "Deskargatu", +"Download %s" => "Deskargatu %s", "Direct link" => "Lotura zuzena" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_sharing/l10n/fa.php b/apps/files_sharing/l10n/fa.php index 1176401f1a..fb6a4bc870 100644 --- a/apps/files_sharing/l10n/fa.php +++ b/apps/files_sharing/l10n/fa.php @@ -1,8 +1,17 @@ "اشتراک گذارنده {owner}", +"This share is password-protected" => "این اشتراک توسط رمز عبور محافظت می شود", "The password is wrong. Try again." => "رمزعبور اشتباه می باشد. دوباره امتحان کنید.", "Password" => "گذرواژه", -"Download" => "دانلود" +"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/km.php b/apps/files_sharing/l10n/km.php index db353c9cb7..75f5679d97 100644 --- a/apps/files_sharing/l10n/km.php +++ b/apps/files_sharing/l10n/km.php @@ -1,6 +1,17 @@ "{owner} បាន​ចែក​រំលែក", +"This share is password-protected" => "ការ​ចែករំលែក​នេះ​ត្រូវ​បាន​ការពារ​ដោយ​ពាក្យ​សម្ងាត់", +"The password is wrong. Try again." => "ពាក្យ​សម្ងាត់​ខុស​ហើយ។ ព្យាយាម​ម្ដង​ទៀត។", "Password" => "ពាក្យសម្ងាត់", -"Download" => "ទាញយក" +"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/ru.php b/apps/files_sharing/l10n/ru.php index 41c60d2ec8..5920d79d9e 100644 --- a/apps/files_sharing/l10n/ru.php +++ b/apps/files_sharing/l10n/ru.php @@ -11,6 +11,7 @@ $TRANSLATIONS = array( "sharing is disabled" => "общий доступ отключён", "For more info, please ask the person who sent this link." => "Пожалуйста, обратитесь к отправителю данной ссылки.", "Download" => "Скачать", +"Download %s" => "Скачать %s", "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/zh_CN.php b/apps/files_sharing/l10n/zh_CN.php index 3178b28405..5cc95b71af 100644 --- a/apps/files_sharing/l10n/zh_CN.php +++ b/apps/files_sharing/l10n/zh_CN.php @@ -11,6 +11,7 @@ $TRANSLATIONS = array( "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/lib/api.php b/apps/files_sharing/lib/api.php index 438d3cc4ba..21fd5d00a4 100644 --- a/apps/files_sharing/lib/api.php +++ b/apps/files_sharing/lib/api.php @@ -25,7 +25,7 @@ namespace OCA\Files\Share; class Api { /** - * @brief get all shares + * get all shares * * @param array $params option 'file' to limit the result to a specific file/folder * @return \OC_OCS_Result share information @@ -60,7 +60,7 @@ class Api { } /** - * @brief get share information for a given share + * get share information for a given share * * @param array $params which contains a 'id' * @return \OC_OCS_Result share information @@ -76,7 +76,7 @@ class Api { } /** - * @brief collect all share information, either of a specific share or all + * collect all share information, either of a specific share or all * shares for a given path * @param array $params * @return \OC_OCS_Result @@ -130,7 +130,7 @@ class Api { } /** - * @brief add reshares to a array of shares + * add reshares to a array of shares * @param array $shares array of shares * @param int $itemSource item source ID * @return array new shares array which includes reshares @@ -161,7 +161,7 @@ class Api { } /** - * @brief get share from all files in a given folder (non-recursive) + * get share from all files in a given folder (non-recursive) * @param array $params contains 'path' to the folder * @return \OC_OCS_Result */ @@ -196,7 +196,7 @@ class Api { } /** - * @breif create a new share + * create a new share * @param array $params * @return \OC_OCS_Result */ @@ -313,7 +313,7 @@ class Api { } /** - * @brief update permissions for a share + * update permissions for a share * @param array $share information about the share * @param array $params contains 'permissions' * @return \OC_OCS_Result @@ -358,7 +358,7 @@ class Api { } /** - * @brief enable/disable public upload + * enable/disable public upload * @param array $share information about the share * @param array $params contains 'publicUpload' which can be 'yes' or 'no' * @return \OC_OCS_Result @@ -384,9 +384,9 @@ class Api { } /** - * @brief update password for public link share + * update password for public link share * @param array $share information about the share - * @param type $params 'password' + * @param array $params 'password' * @return \OC_OCS_Result */ private static function updatePassword($share, $params) { @@ -418,13 +418,18 @@ class Api { return new \OC_OCS_Result(null, 404, "share doesn't exists, can't change password"); } - $result = \OCP\Share::shareItem( - $itemType, - $itemSource, - \OCP\Share::SHARE_TYPE_LINK, - $shareWith, - $permissions - ); + try { + $result = \OCP\Share::shareItem( + $itemType, + $itemSource, + \OCP\Share::SHARE_TYPE_LINK, + $shareWith, + $permissions + ); + } catch (\Exception $e) { + return new \OC_OCS_Result(null, 403, $e->getMessage()); + } + if($result) { return new \OC_OCS_Result(); } @@ -433,7 +438,7 @@ class Api { } /** - * @brief unshare a file/folder + * unshare a file/folder * @param array $params contains the shareID 'id' which should be unshared * @return \OC_OCS_Result */ @@ -473,7 +478,7 @@ class Api { } /** - * @brief get file ID from a given path + * get file ID from a given path * @param string $path * @return string fileID or null */ @@ -490,7 +495,7 @@ class Api { } /** - * @brief get itemType + * get itemType * @param string $path * @return string type 'file', 'folder' or null of file/folder doesn't exists */ @@ -508,7 +513,7 @@ class Api { } /** - * @brief get some information from a given share + * get some information from a given share * @param int $shareID * @return array with: item_source, share_type, share_with, item_type, permissions */ diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 1f316301c4..9d83ed13b8 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -42,7 +42,7 @@ class Shared_Cache extends Cache { } /** - * @brief Get the source cache of a shared file or folder + * Get the source cache of a shared file or folder * @param string $target Shared target file path * @return \OC\Files\Cache\Cache */ @@ -80,7 +80,7 @@ class Shared_Cache extends Cache { /** * get the stored metadata of a file or folder * - * @param string /int $file + * @param string|int $file * @return array */ public function get($file) { @@ -424,7 +424,7 @@ class Shared_Cache extends Cache { * * @param int $id * @param string $pathEnd (optional) used internally for recursive calls - * @return string | null + * @return string|null */ public function getPathById($id, $pathEnd = '') { // direct shares are easy @@ -442,6 +442,9 @@ class Shared_Cache extends Cache { } } + /** + * @param integer $id + */ private function getShareById($id) { $item = \OCP\Share::getItemSharedWithBySource('file', $id); if ($item) { @@ -454,6 +457,9 @@ class Shared_Cache extends Cache { return null; } + /** + * @param integer $id + */ private function getParentInfo($id) { $sql = 'SELECT `parent`, `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?'; $query = \OC_DB::prepare($sql); diff --git a/apps/files_sharing/lib/helper.php b/apps/files_sharing/lib/helper.php index cc1f7d9ffd..71b496ab94 100644 --- a/apps/files_sharing/lib/helper.php +++ b/apps/files_sharing/lib/helper.php @@ -79,7 +79,7 @@ class Helper { * @param array $linkItem link item array * @param string $password optional password * - * @return true if authorized, false otherwise + * @return boolean true if authorized, false otherwise */ public static function authenticate($linkItem, $password) { if ($password !== null) { @@ -125,9 +125,13 @@ class Helper { $ids = array(); - while ($path !== '' && $path !== '.' && $path !== '/') { + while ($path !== dirname($path)) { $info = $ownerView->getFileInfo($path); - $ids[] = $info['fileid']; + 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); } @@ -158,7 +162,7 @@ class Helper { } /** - * @brief Format a path to be relative to the /user/files/ directory + * 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' */ diff --git a/apps/files_sharing/lib/maintainer.php b/apps/files_sharing/lib/maintainer.php index bbb3268410..f07c09e5ae 100644 --- a/apps/files_sharing/lib/maintainer.php +++ b/apps/files_sharing/lib/maintainer.php @@ -33,7 +33,7 @@ class Maintainer { * Keeps track of the "allow links" config setting * and removes all link shares if the config option is set to "no" * - * @param array with app, key, value as named values + * @param array $params array with app, key, value as named values */ static public function configChangeHook($params) { if($params['app'] === 'core' && $params['key'] === 'shareapi_allow_links' && $params['value'] === 'no') { diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index c0c9e0c107..af71786b10 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -33,10 +33,12 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { private $path; public function isValidSource($itemSource, $uidOwner) { - $query = \OC_DB::prepare('SELECT `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?'); - $result = $query->execute(array($itemSource)); - if ($row = $result->fetchRow()) { - $this->path = $row['name']; + $path = \OC\Files\Filesystem::getPath($itemSource); + if ($path) { + // FIXME: attributes should not be set here, + // keeping this pattern for now to avoid unexpected + // regressions + $this->path = basename($path); return true; } return false; @@ -52,7 +54,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { } /** - * @brief create unique target + * create unique target * @param string $filePath * @param string $shareWith * @param string $exclude @@ -152,7 +154,7 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { } /** - * @brief resolve reshares to return the correct source item + * resolve reshares to return the correct source item * @param array $source * @return array source item */ @@ -181,8 +183,13 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { return $source; } + /** + * @param string $target + * @param string $mountPoint + * @param string $itemType + * @return array|false source item + */ 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 !== '') { diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 4733dff3d1..4b69276d05 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -36,7 +36,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @breif get id of the mount point + * get id of the mount point * @return string */ public function getId() { @@ -44,7 +44,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @breif get file cache of the shared item source + * get file cache of the shared item source * @return string */ public function getSourceId() { @@ -52,9 +52,8 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief Get the source file path, permissions, and owner for a shared file - * @param string Shared target file path - * @param string $target + * Get the source file path, permissions, and owner for a shared file + * @param string $target Shared target file path * @return Returns array with the keys path, permissions, and owner or false if not found */ public function getFile($target) { @@ -76,9 +75,8 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief Get the source file path for a shared file - * @param string Shared target file path - * @param string $target + * Get the source file path for a shared file + * @param string $target Shared target file path * @return string source file path or false if not found */ public function getSourcePath($target) { @@ -100,16 +98,17 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief Get the permissions granted for a shared file - * @param string Shared target file path - * @return int CRUDS permissions granted or false if not found + * Get the permissions granted for a shared file + * @param string $target Shared target file path + * @return int CRUDS permissions granted */ public function getPermissions($target) { - $source = $this->getFile($target); - if ($source) { - return $source['permissions']; + $permissions = $this->share['permissions']; + // part file are always have delete permissions + if (pathinfo($target, PATHINFO_EXTENSION) === 'part') { + $permissions |= \OCP\PERMISSION_DELETE; } - return false; + return $permissions; } public function mkdir($path) { @@ -183,9 +182,6 @@ class Shared extends \OC\Files\Storage\Common { } public function isCreatable($path) { - if ($path == '') { - $path = $this->getMountPoint(); - } return ($this->getPermissions($path) & \OCP\PERMISSION_CREATE); } @@ -194,23 +190,14 @@ class Shared extends \OC\Files\Storage\Common { } public function isUpdatable($path) { - if ($path == '') { - $path = $this->getMountPoint(); - } return ($this->getPermissions($path) & \OCP\PERMISSION_UPDATE); } public function isDeletable($path) { - if ($path == '') { - $path = $this->getMountPoint(); - } return ($this->getPermissions($path) & \OCP\PERMISSION_DELETE); } public function isSharable($path) { - if ($path == '') { - $path = $this->getMountPoint(); - } return ($this->getPermissions($path) & \OCP\PERMISSION_SHARE); } @@ -276,7 +263,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief Format a path to be relative to the /user/files/ directory + * 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' */ @@ -300,7 +287,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief rename a shared folder/file + * rename a shared folder/file * @param string $sourcePath * @param string $targetPath * @return bool @@ -454,9 +441,6 @@ class Shared extends \OC\Files\Storage\Common { } public function free_space($path) { - if ($path == '') { - $path = $this->getMountPoint(); - } $source = $this->getSourcePath($path); if ($source) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); @@ -497,7 +481,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief return mount point of share, relative to data/user/files + * return mount point of share, relative to data/user/files * @return string */ public function getMountPoint() { @@ -505,7 +489,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief get share type + * get share type * @return integer can be single user share (0) group share (1), unique group share name (2) */ private function getShareType() { @@ -517,7 +501,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief does the group share already has a user specific unique name + * does the group share already has a user specific unique name * @return bool */ private function uniqueNameSet() { @@ -525,14 +509,14 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief the share now uses a unique name of this user + * the share now uses a unique name of this user */ private function setUniqueName() { $this->share['unique_name'] = true; } /** - * @brief get share ID + * get share ID * @return integer unique share ID */ private function getShareId() { @@ -540,7 +524,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief get the user who shared the file + * get the user who shared the file * @return string */ public function getSharedFrom() { @@ -548,7 +532,7 @@ class Shared extends \OC\Files\Storage\Common { } /** - * @brief return share type, can be "file" or "folder" + * return share type, can be "file" or "folder" * @return string */ public function getItemType() { diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index f7c0a75aee..21d67caad9 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -27,7 +27,7 @@ class Shared_Updater { static private $toRemove = array(); /** - * @brief walk up the users file tree and update the etags + * walk up the users file tree and update the etags * @param string $user * @param string $path */ @@ -38,14 +38,13 @@ class Shared_Updater { \OC\Files\Filesystem::initMountPoints($user); $view = new \OC\Files\View('/' . $user); if ($view->file_exists($path)) { - while ($path !== '/') { + while ($path !== dirname($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); + \OCP\Util::writeLog('files_sharing', 'can not update etags on ' . $path . ' for user ' . $user . '. Path does not exists', \OCP\Util::DEBUG); } } @@ -55,6 +54,12 @@ class Shared_Updater { * @param string $target */ static public function correctFolders($target) { + + // ignore part files + if (pathinfo($target, PATHINFO_EXTENSION) === 'part') { + return false; + } + // Correct Shared folders of other users shared with $shares = \OCA\Files_Sharing\Helper::getSharesFromItem($target); @@ -73,7 +78,7 @@ class Shared_Updater { } /** - * @brief remove all shares for a given file if the file was deleted + * remove all shares for a given file if the file was deleted * * @param string $path */ diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index e17ffc4803..8a86cb3806 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -149,11 +149,11 @@ if (isset($path)) { $freeSpace=OCP\Util::freeSpace($path); $uploadLimit=OCP\Util::uploadLimit(); - $folder = new OCP\Template('files', 'index', ''); + $folder = new OCP\Template('files', 'list', ''); $folder->assign('dir', $getPath); $folder->assign('dirToken', $linkItem['token']); $folder->assign('permissions', OCP\PERMISSION_READ); - $folder->assign('isPublic',true); + $folder->assign('isPublic', true); $folder->assign('publicUploadEnabled', 'no'); $folder->assign('files', $files); $folder->assign('uploadMaxFilesize', $maxUploadFilesize); @@ -162,7 +162,6 @@ 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('disableSharing', true); $folder->assign('trash', false); $tmpl->assign('folder', $folder->fetchPage()); $allowZip = OCP\Config::getSystemValue('allowZipDownload', true); diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index f3c75134a5..9471752b6b 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -30,7 +30,6 @@
-
diff --git a/apps/files_sharing/tests/api.php b/apps/files_sharing/tests/api.php index b2f05d10ac..dc07c6fc62 100644 --- a/apps/files_sharing/tests/api.php +++ b/apps/files_sharing/tests/api.php @@ -29,10 +29,14 @@ use OCA\Files\Share; */ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { + const TEST_FOLDER_NAME = '/folder_share_api_test'; + + private static $tempStorage; + function setUp() { parent::setUp(); - $this->folder = '/folder_share_api_test'; + $this->folder = self::TEST_FOLDER_NAME; $this->subfolder = '/subfolder_share_api_test'; $this->subsubfolder = '/subsubfolder_share_api_test'; @@ -51,6 +55,8 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $this->view->unlink($this->filename); $this->view->deleteAll($this->folder); + self::$tempStorage = null; + parent::tearDown(); } @@ -107,11 +113,65 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $fileinfo = $this->view->getFileInfo($this->folder); \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null); - - - } + function testEnfoceLinkPassword() { + + $appConfig = \OC::$server->getAppConfig(); + $appConfig->setValue('core', 'shareapi_enforce_links_password', 'yes'); + + // don't allow to share link without a password + $_POST['path'] = $this->folder; + $_POST['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + + + $result = Share\Api::createShare(array()); + $this->assertFalse($result->succeeded()); + + + // don't allow to share link without a empty password + $_POST['path'] = $this->folder; + $_POST['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + $_POST['password'] = ''; + + $result = Share\Api::createShare(array()); + $this->assertFalse($result->succeeded()); + + // share with password should succeed + $_POST['path'] = $this->folder; + $_POST['shareType'] = \OCP\Share::SHARE_TYPE_LINK; + $_POST['password'] = 'foo'; + + $result = Share\Api::createShare(array()); + $this->assertTrue($result->succeeded()); + + $data = $result->getData(); + + // setting new password should succeed + $params = array(); + $params['id'] = $data['id']; + $params['_put'] = array(); + $params['_put']['password'] = 'bar'; + + $result = Share\Api::updateShare($params); + $this->assertTrue($result->succeeded()); + + // removing password should fail + $params = array(); + $params['id'] = $data['id']; + $params['_put'] = array(); + $params['_put']['password'] = ''; + + $result = Share\Api::updateShare($params); + $this->assertFalse($result->succeeded()); + + // cleanup + $fileinfo = $this->view->getFileInfo($this->folder); + \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_LINK, null); + $appConfig->setValue('core', 'shareapi_enforce_links_password', 'no'); + } + + /** * @medium * @depends testCreateShare @@ -127,7 +187,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $this->assertTrue($result->succeeded()); - // test should return two shares created from testCreateShare() + // test should return two shares created from testCreateShare() $this->assertTrue(count($result->getData()) === 1); \OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER, @@ -154,7 +214,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $this->assertTrue($result->succeeded()); - // test should return one share created from testCreateShare() + // test should return one share created from testCreateShare() $this->assertTrue(count($result->getData()) === 2); \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, @@ -281,7 +341,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $this->assertTrue($result->succeeded()); - // test should return one share within $this->folder + // test should return one share within $this->folder $this->assertTrue(count($result->getData()) === 1); \OCP\Share::unshare('file', $fileInfo1['fileid'], \OCP\Share::SHARE_TYPE_USER, @@ -292,7 +352,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief share a folder, than reshare a file within the shared folder and check if we construct the correct path + * share a folder, than reshare a file within the shared folder and check if we construct the correct path * @medium */ function testGetShareFromFolderReshares() { @@ -357,7 +417,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief reshare a sub folder and check if we get the correct path + * reshare a sub folder and check if we get the correct path * @medium */ function testGetShareFromSubFolderReShares() { @@ -410,7 +470,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief test re-re-share of folder if the path gets constructed correctly + * test re-re-share of folder if the path gets constructed correctly * @medium */ function testGetShareFromFolderReReShares() { @@ -478,7 +538,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief test multiple shared folder if the path gets constructed correctly + * test multiple shared folder if the path gets constructed correctly * @medium */ function testGetShareMultipleSharedFolder() { @@ -561,7 +621,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief test re-re-share of folder if the path gets constructed correctly + * test re-re-share of folder if the path gets constructed correctly * @medium */ function testGetShareFromFileReReShares() { @@ -638,7 +698,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $result = Share\Api::getShare($params); $this->assertEquals(404, $result->getStatusCode()); - $meta = $result->getMeta(); + $meta = $result->getMeta(); $this->assertEquals('share doesn\'t exist', $meta['message']); } @@ -695,7 +755,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { $result = Share\Api::updateShare($params); - $meta = $result->getMeta(); + $meta = $result->getMeta(); $this->assertTrue($result->succeeded(), $meta['message']); $items = \OCP\Share::getItemShared('file', $userShare['file_source']); @@ -835,7 +895,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief test unshare of a reshared file + * test unshare of a reshared file */ function testDeleteReshare() { @@ -879,7 +939,7 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { } /** - * @brief share a folder which contains a share mount point, should be forbidden + * share a folder which contains a share mount point, should be forbidden */ public function testShareFolderWithAMountPoint() { // user 1 shares a folder with user2 @@ -928,6 +988,54 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); } + /** + * Post init mount points hook for mounting simulated ext storage + */ + public static function initTestMountPointsHook($data) { + if ($data['user'] === \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1) { + \OC\Files\Filesystem::mount(self::$tempStorage, array(), '/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1 . '/files' . self::TEST_FOLDER_NAME); + } + } + + /** + * Tests mounting a folder that is an external storage mount point. + */ + public function testShareStorageMountPoint() { + self::$tempStorage = new \OC\Files\Storage\Temporary(array()); + self::$tempStorage->file_put_contents('test.txt', 'abcdef'); + self::$tempStorage->getScanner()->scan(''); + + // needed because the sharing code sometimes switches the user internally and mounts the user's + // storages. In our case the temp storage isn't mounted automatically, so doing it in the post hook + // (similar to how ext storage works) + OCP\Util::connectHook('OC_Filesystem', 'post_initMountPoints', '\Test_Files_Sharing_Api', 'initTestMountPointsHook'); + + // logging in will auto-mount the temp storage for user1 as well + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); + + $fileInfo = $this->view->getFileInfo($this->folder); + + // user 1 shares the mount point folder with user2 + $result = \OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); + + $this->assertTrue($result); + + // user2: check that mount point name appears correctly + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); + + $view = new \OC\Files\View('/' . \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2 . '/files'); + + $this->assertTrue($view->file_exists($this->folder)); + $this->assertTrue($view->file_exists($this->folder . '/test.txt')); + + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); + + \OCP\Share::unshare('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, + \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); + + \OC_Hook::clear('OC_Filesystem', 'post_initMountPoints', '\Test_Files_Sharing_Api', 'initTestMountPointsHook'); + } /** * @expectedException \Exception */ @@ -951,4 +1059,57 @@ class Test_Files_Sharing_Api extends Test_Files_Sharing_Base { \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); } + public function testDefaultExpireDate() { + \Test_Files_Sharing_Api::loginHelper(\Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER1); + \OC_Appconfig::setValue('core', 'shareapi_default_expire_date', 'yes'); + \OC_Appconfig::setValue('core', 'shareapi_enforce_expire_date', 'yes'); + \OC_Appconfig::setValue('core', 'shareapi_expire_after_n_days', '2'); + + // default expire date is set to 2 days + // the time when the share was created is set to 3 days in the past + // user defined expire date is set to +2 days from now on + // -> link should be already expired by the default expire date but the user + // share should still exists. + $now = time(); + $dateFormat = 'Y-m-d H:i:s'; + $shareCreated = $now - 3 * 24 * 60 * 60; + $expireDate = date($dateFormat, $now + 2 * 24 * 60 * 60); + + $info = OC\Files\Filesystem::getFileInfo($this->filename); + $this->assertTrue($info instanceof \OC\Files\FileInfo); + + $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_LINK, null, \OCP\PERMISSION_READ); + $this->assertTrue(is_string($result)); + + $result = \OCP\Share::shareItem('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2, 31); + $this->assertTrue($result); + + $result = \OCP\Share::setExpirationDate('file', $info->getId() , $expireDate); + $this->assertTrue($result); + + //manipulate stime so that both shares are older then the default expire date + $statement = "UPDATE `*PREFIX*share` SET `stime` = ? WHERE `share_type` = ?"; + $query = \OCP\DB::prepare($statement); + $result = $query->execute(array($shareCreated, \OCP\Share::SHARE_TYPE_LINK)); + $this->assertSame(1, $result); + $statement = "UPDATE `*PREFIX*share` SET `stime` = ? WHERE `share_type` = ?"; + $query = \OCP\DB::prepare($statement); + $result = $query->execute(array($shareCreated, \OCP\Share::SHARE_TYPE_USER)); + $this->assertSame(1, $result); + + // now the link share should expire because of enforced default expire date + // the user share should still exist + $result = \OCP\Share::getItemShared('file', $info->getId()); + $this->assertTrue(is_array($result)); + $this->assertSame(1, count($result)); + $share = reset($result); + $this->assertSame(\OCP\Share::SHARE_TYPE_USER, $share['share_type']); + + //cleanup + $result = \OCP\Share::unshare('file', $info->getId(), \OCP\Share::SHARE_TYPE_USER, \Test_Files_Sharing_Api::TEST_FILES_SHARING_API_USER2); + $this->assertTrue($result); + \OC_Appconfig::setValue('core', 'shareapi_default_expire_date', 'no'); + \OC_Appconfig::setValue('core', 'shareapi_enforce_expire_date', 'no'); + + } } diff --git a/apps/files_sharing/tests/base.php b/apps/files_sharing/tests/base.php index 495dca072c..7cd36b9d41 100644 --- a/apps/files_sharing/tests/base.php +++ b/apps/files_sharing/tests/base.php @@ -39,7 +39,7 @@ abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase { public $filename; public $data; /** - * @var OC_FilesystemView + * @var OC\Files\View */ public $view; public $folder; @@ -68,7 +68,7 @@ abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase { self::loginHelper(self::TEST_FILES_SHARING_API_USER1); $this->data = 'foobar'; - $this->view = new \OC_FilesystemView('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); + $this->view = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files'); // remember files_encryption state $this->stateFilesEncryption = \OC_App::isEnabled('files_encryption'); @@ -97,7 +97,7 @@ abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase { } /** - * @param $user + * @param string $user * @param bool $create * @param bool $password */ @@ -119,7 +119,7 @@ abstract class Test_Files_Sharing_Base extends \PHPUnit_Framework_TestCase { } /** - * @brief get some information from a given share + * get some information from a given share * @param int $shareID * @return array with: item_source, share_type, share_with, item_type, permissions */ diff --git a/apps/files_sharing/tests/cache.php b/apps/files_sharing/tests/cache.php index 1af73c558d..c5408ba55e 100644 --- a/apps/files_sharing/tests/cache.php +++ b/apps/files_sharing/tests/cache.php @@ -25,7 +25,7 @@ require_once __DIR__ . '/base.php'; class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base { /** - * @var OC_FilesystemView + * @var OC\Files\View */ public $user2View; @@ -230,7 +230,7 @@ class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base { } /** - * @brief verify if each value from the result matches the expected result + * verify if each value from the result matches the expected result * @param array $example array with the expected results * @param array $result array with the results */ diff --git a/apps/files_trashbin/ajax/list.php b/apps/files_trashbin/ajax/list.php index 89a5511452..e1f52e814b 100644 --- a/apps/files_trashbin/ajax/list.php +++ b/apps/files_trashbin/ajax/list.php @@ -4,11 +4,13 @@ OCP\JSON::checkLoggedIn(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; +$sortAttribute = isset( $_GET['sort'] ) ? $_GET['sort'] : 'name'; +$sortDirection = isset( $_GET['sortdirection'] ) ? ($_GET['sortdirection'] === 'desc') : false; $data = array(); // make filelist try { - $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir); + $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir, $sortAttribute, $sortDirection); } catch (Exception $e) { header("HTTP/1.0 404 Not Found"); exit(); diff --git a/apps/files_trashbin/appinfo/app.php b/apps/files_trashbin/appinfo/app.php index d30a601ef5..b8900ee0de 100644 --- a/apps/files_trashbin/appinfo/app.php +++ b/apps/files_trashbin/appinfo/app.php @@ -1,7 +1,15 @@ add( +array( + "id" => 'trashbin', + "appname" => 'files_trashbin', + "script" => 'list.php', + "order" => 1, + "name" => $l->t('Deleted files') +) +); diff --git a/apps/files_trashbin/appinfo/routes.php b/apps/files_trashbin/appinfo/routes.php index b1c3f02741..42398a06c8 100644 --- a/apps/files_trashbin/appinfo/routes.php +++ b/apps/files_trashbin/appinfo/routes.php @@ -1,5 +1,6 @@ create('core_ajax_trashbin_preview', '/preview.png')->action( +/** @var $this \OCP\Route\IRouter */ +$this->create('core_ajax_trashbin_preview', '/preview')->action( function() { require_once __DIR__ . '/../ajax/preview.php'; -}); \ No newline at end of file +}); diff --git a/apps/files_trashbin/css/trash.css b/apps/files_trashbin/css/trash.css index 7ca3e355fc..04b4a175c8 100644 --- a/apps/files_trashbin/css/trash.css +++ b/apps/files_trashbin/css/trash.css @@ -1,4 +1,13 @@ -#fileList tr[data-type="file"] td a.name, -#fileList tr[data-type="file"] td a.name span { +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ +#app-content-trashbin tbody tr[data-type="file"] td a.name, +#app-content-trashbin tbody tr[data-type="file"] td a.name span { cursor: default; } diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php deleted file mode 100644 index 6e6a8a3830..0000000000 --- a/apps/files_trashbin/index.php +++ /dev/null @@ -1,42 +0,0 @@ - 0 && $matches[1] <= 8){ - $isIE8 = true; -} - -// if IE8 and "?dir=path" was specified, reformat the URL to use a hash like "#?dir=path" -if ($isIE8 && isset($_GET['dir'])){ - if ($dir === ''){ - $dir = '/'; - } - header('Location: ' . OCP\Util::linkTo('files_trashbin', 'index.php') . '#?dir=' . \OCP\Util::encodePath($dir)); - exit(); -} - -$tmpl->assign('dir', $dir); -$tmpl->assign('disableSharing', true); - -$tmpl->printPage(); diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js new file mode 100644 index 0000000000..aa499ae179 --- /dev/null +++ b/apps/files_trashbin/js/app.js @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + +OCA.Trashbin = {}; +OCA.Trashbin.App = { + _initialized: false, + + initialize: function($el) { + if (this._initialized) { + return; + } + this._initialized = true; + this.fileList = new OCA.Trashbin.FileList( + $('#app-content-trashbin'), { + scrollContainer: $('#app-content') + } + ); + this.registerFileActions(this.fileList); + }, + + registerFileActions: function(fileList) { + var self = this; + var fileActions = _.extend({}, OCA.Files.FileActions); + fileActions.clear(); + fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) { + var dir = fileList.getCurrentDirectory(); + if (dir !== '/') { + dir = dir + '/'; + } + fileList.changeDirectory(dir + filename); + }); + + fileActions.setDefault('dir', 'Open'); + + fileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/history'), function(filename) { + var tr = fileList.findFileEl(filename); + var deleteAction = tr.children("td.date").children(".action.delete"); + deleteAction.removeClass('delete-icon').addClass('progress-icon'); + fileList.disableActions(); + $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), { + files: JSON.stringify([filename]), + dir: fileList.getCurrentDirectory() + }, + _.bind(fileList._removeCallback, fileList) + ); + }, t('files_trashbin', 'Restore')); + + fileActions.register('all', 'Delete', OC.PERMISSION_READ, function() { + return OC.imagePath('core', 'actions/delete'); + }, function(filename) { + $('.tipsy').remove(); + var tr = fileList.findFileEl(filename); + var deleteAction = tr.children("td.date").children(".action.delete"); + deleteAction.removeClass('delete-icon').addClass('progress-icon'); + fileList.disableActions(); + $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), { + files: JSON.stringify([filename]), + dir: fileList.getCurrentDirectory() + }, + _.bind(fileList._removeCallback, fileList) + ); + }); + fileList.setFileActions(fileActions); + } +}; + +$(document).ready(function() { + $('#app-content-trashbin').one('show', function() { + var App = OCA.Trashbin.App; + App.initialize($('#app-content-trashbin')); + // force breadcrumb init + // App.fileList.changeDirectory(App.fileList.getCurrentDirectory(), false, true); + }); +}); + diff --git a/apps/files_trashbin/js/disableDefaultActions.js b/apps/files_trashbin/js/disableDefaultActions.js deleted file mode 100644 index 50ceaf4696..0000000000 --- a/apps/files_trashbin/js/disableDefaultActions.js +++ /dev/null @@ -1,3 +0,0 @@ -/* disable download and sharing actions */ -var disableDownloadActions = true; -var trashBinApp = true; diff --git a/apps/files_trashbin/js/filelist.js b/apps/files_trashbin/js/filelist.js index 3bb3a92b60..205f879f33 100644 --- a/apps/files_trashbin/js/filelist.js +++ b/apps/files_trashbin/js/filelist.js @@ -1,8 +1,14 @@ -/* global OC, t, FileList */ +/* + * Copyright (c) 2014 + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ (function() { - FileList.appName = t('files_trashbin', 'Deleted files'); - - FileList._deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/); + var DELETED_REGEXP = new RegExp(/^(.+)\.d[0-9]+$/); /** * Convert a file name in the format filename.d12345 to the real file name. @@ -11,194 +17,248 @@ * @param name file name * @return converted file name */ - FileList.getDeletedFileName = function(name) { + function getDeletedFileName(name) { name = OC.basename(name); - var match = FileList._deletedRegExp.exec(name); + var match = DELETED_REGEXP.exec(name); if (match && match.length > 1) { name = match[1]; } return name; - }; - - var oldSetCurrentDir = FileList._setCurrentDir; - FileList._setCurrentDir = function(targetDir) { - oldSetCurrentDir.apply(this, arguments); - - var baseDir = OC.basename(targetDir); - if (baseDir !== '') { - FileList.setPageTitle(FileList.getDeletedFileName(baseDir)); - } - }; - - var oldCreateRow = FileList._createRow; - FileList._createRow = function() { - // FIXME: MEGAHACK until we find a better solution - var tr = oldCreateRow.apply(this, arguments); - tr.find('td.filesize').remove(); - return tr; - }; - - FileList._onClickBreadCrumb = function(e) { - var $el = $(e.target).closest('.crumb'), - index = $el.index(), - $targetDir = $el.data('dir'); - // first one is home, let the link makes it default action - if (index !== 0) { - e.preventDefault(); - FileList.changeDirectory($targetDir); - } - }; - - var oldRenderRow = FileList._renderRow; - FileList._renderRow = function(fileData, options) { - options = options || {}; - var dir = FileList.getCurrentDirectory(); - var dirListing = dir !== '' && dir !== '/'; - // show deleted time as mtime - if (fileData.mtime) { - fileData.mtime = parseInt(fileData.mtime, 10); - } - if (!dirListing) { - fileData.displayName = fileData.name; - fileData.name = fileData.name + '.d' + Math.floor(fileData.mtime / 1000); - } - return oldRenderRow.call(this, fileData, options); - }; - - FileList.linkTo = function(dir){ - return OC.linkTo('files_trashbin', 'index.php')+"?dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); - }; - - FileList.updateEmptyContent = function(){ - var $fileList = $('#fileList'); - var exists = $fileList.find('tr:first').exists(); - $('#emptycontent').toggleClass('hidden', exists); - $('#filestable th').toggleClass('hidden', !exists); - }; - - var oldInit = FileList.initialize; - FileList.initialize = function() { - var result = oldInit.apply(this, arguments); - $('.undelete').click('click', FileList._onClickRestoreSelected); - return result; - }; - - FileList._removeCallback = function(result) { - if (result.status !== 'success') { - OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error')); - } - - var files = result.data.success; - var $el; - for (var i = 0; i < files.length; i++) { - $el = FileList.remove(OC.basename(files[i].filename), {updateSummary: false}); - FileList.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')}); - } - FileList.fileSummary.update(); - FileList.updateEmptyContent(); - enableActions(); } - FileList._onClickRestoreSelected = function(event) { - event.preventDefault(); - var allFiles = $('#select_all').is(':checked'); - var files = []; - var params = {}; - disableActions(); - if (allFiles) { - FileList.showMask(); - params = { - allfiles: true, - dir: FileList.getCurrentDirectory() - }; - } - else { - files = _.pluck(FileList.getSelectedFiles(), 'name'); - for (var i = 0; i < files.length; i++) { - var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); - deleteAction.removeClass('delete-icon').addClass('progress-icon'); - } - params = { - files: JSON.stringify(files), - dir: FileList.getCurrentDirectory() - }; - } - - $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), - params, - function(result) { - if (allFiles) { - if (result.status !== 'success') { - OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error')); - } - FileList.hideMask(); - // simply remove all files - FileList.setFiles([]); - enableActions(); - } - else { - FileList._removeCallback(result); - } - } - ); + var FileList = function($el) { + this.initialize($el); }; + FileList.prototype = _.extend({}, OCA.Files.FileList.prototype, { + id: 'trashbin', + appName: t('files_trashbin', 'Deleted files'), - FileList._onClickDeleteSelected = function(event) { - event.preventDefault(); - var allFiles = $('#select_all').is(':checked'); - var files = []; - var params = {}; - if (allFiles) { - params = { - allfiles: true, - dir: FileList.getCurrentDirectory() - }; - } - else { - files = _.pluck(FileList.getSelectedFiles(), 'name'); - params = { - files: JSON.stringify(files), - dir: FileList.getCurrentDirectory() - }; - } + initialize: function() { + var result = OCA.Files.FileList.prototype.initialize.apply(this, arguments); + this.$el.find('.undelete').click('click', _.bind(this._onClickRestoreSelected, this)); - disableActions(); - if (allFiles) { - FileList.showMask(); - } - else { - for (var i = 0; i < files.length; i++) { - var deleteAction = FileList.findFileEl(files[i]).children("td.date").children(".action.delete"); - deleteAction.removeClass('delete-icon').addClass('progress-icon'); + this.setSort('mtime', 'desc'); + /** + * Override crumb making to add "Deleted Files" entry + * and convert files with ".d" extensions to a more + * user friendly name. + */ + this.breadcrumb._makeCrumbs = function() { + var parts = OCA.Files.BreadCrumb.prototype._makeCrumbs.apply(this, arguments); + for (var i = 1; i < parts.length; i++) { + parts[i].name = getDeletedFileName(parts[i].name); + } + return parts; + }; + + return result; + }, + + /** + * Override to only return read permissions + */ + getDirectoryPermissions: function() { + return OC.PERMISSION_READ | OC.PERMISSION_DELETE; + }, + + _setCurrentDir: function(targetDir) { + OCA.Files.FileList.prototype._setCurrentDir.apply(this, arguments); + + var baseDir = OC.basename(targetDir); + if (baseDir !== '') { + this.setPageTitle(getDeletedFileName(baseDir)); } - } + }, - $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), + _createRow: function() { + // FIXME: MEGAHACK until we find a better solution + var tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments); + tr.find('td.filesize').remove(); + return tr; + }, + + _renderRow: function(fileData, options) { + options = options || {}; + var dir = this.getCurrentDirectory(); + var dirListing = dir !== '' && dir !== '/'; + // show deleted time as mtime + if (fileData.mtime) { + fileData.mtime = parseInt(fileData.mtime, 10); + } + if (!dirListing) { + fileData.displayName = fileData.name; + fileData.name = fileData.name + '.d' + Math.floor(fileData.mtime / 1000); + } + return OCA.Files.FileList.prototype._renderRow.call(this, fileData, options); + }, + + getAjaxUrl: function(action, params) { + var q = ''; + if (params) { + q = '?' + OC.buildQueryString(params); + } + return OC.filePath('files_trashbin', 'ajax', action + '.php') + q; + }, + + setupUploadEvents: function() { + // override and do nothing + }, + + linkTo: function(dir){ + return OC.linkTo('files', 'index.php')+"?view=trashbin&dir="+ encodeURIComponent(dir).replace(/%2F/g, '/'); + }, + + updateEmptyContent: function(){ + var exists = this.$fileList.find('tr:first').exists(); + this.$el.find('#emptycontent').toggleClass('hidden', exists); + this.$el.find('#filestable th').toggleClass('hidden', !exists); + }, + + _removeCallback: function(result) { + if (result.status !== 'success') { + OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error')); + } + + var files = result.data.success; + var $el; + for (var i = 0; i < files.length; i++) { + $el = this.remove(OC.basename(files[i].filename), {updateSummary: false}); + this.fileSummary.remove({type: $el.attr('data-type'), size: $el.attr('data-size')}); + } + this.fileSummary.update(); + this.updateEmptyContent(); + this.enableActions(); + }, + + _onClickRestoreSelected: function(event) { + event.preventDefault(); + var self = this; + var allFiles = this.$el.find('.select-all').is(':checked'); + var files = []; + var params = {}; + this.disableActions(); + if (allFiles) { + this.showMask(); + params = { + allfiles: true, + dir: this.getCurrentDirectory() + }; + } + else { + files = _.pluck(this.getSelectedFiles(), 'name'); + for (var i = 0; i < files.length; i++) { + var deleteAction = this.findFileEl(files[i]).children("td.date").children(".action.delete"); + deleteAction.removeClass('delete-icon').addClass('progress-icon'); + } + params = { + files: JSON.stringify(files), + dir: this.getCurrentDirectory() + }; + } + + $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), params, function(result) { if (allFiles) { if (result.status !== 'success') { OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error')); } - FileList.hideMask(); + self.hideMask(); // simply remove all files - FileList.setFiles([]); - enableActions(); + self.setFiles([]); + self.enableActions(); } else { - FileList._removeCallback(result); + self._removeCallback(result); } } - ); - }; + ); + }, - var oldClickFile = FileList._onClickFile; - FileList._onClickFile = function(event) { - var mime = $(this).parent().parent().data('mime'); - if (mime !== 'httpd/unix-directory') { + _onClickDeleteSelected: function(event) { event.preventDefault(); - } - return oldClickFile.apply(this, arguments); - }; + var self = this; + var allFiles = this.$el.find('.select-all').is(':checked'); + var files = []; + var params = {}; + if (allFiles) { + params = { + allfiles: true, + dir: this.getCurrentDirectory() + }; + } + else { + files = _.pluck(this.getSelectedFiles(), 'name'); + params = { + files: JSON.stringify(files), + dir: this.getCurrentDirectory() + }; + } + this.disableActions(); + if (allFiles) { + this.showMask(); + } + else { + for (var i = 0; i < files.length; i++) { + var deleteAction = this.findFileEl(files[i]).children("td.date").children(".action.delete"); + deleteAction.removeClass('delete-icon').addClass('progress-icon'); + } + } + + $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), + params, + function(result) { + if (allFiles) { + if (result.status !== 'success') { + OC.dialogs.alert(result.data.message, t('files_trashbin', 'Error')); + } + self.hideMask(); + // simply remove all files + self.setFiles([]); + self.enableActions(); + } + else { + self._removeCallback(result); + } + } + ); + }, + + _onClickFile: function(event) { + var mime = $(this).parent().parent().data('mime'); + if (mime !== 'httpd/unix-directory') { + event.preventDefault(); + } + return OCA.Files.FileList.prototype._onClickFile.apply(this, arguments); + }, + + generatePreviewUrl: function(urlSpec) { + return OC.generateUrl('/apps/files_trashbin/ajax/preview.php?') + $.param(urlSpec); + }, + + getDownloadUrl: function() { + // no downloads + return '#'; + }, + + enableActions: function() { + this.$el.find('.action').css('display', 'inline'); + this.$el.find(':input:checkbox').css('display', 'inline'); + }, + + disableActions: function() { + this.$el.find('.action').css('display', 'none'); + this.$el.find(':input:checkbox').css('display', 'none'); + }, + + updateStorageStatistics: function() { + // no op because the trashbin doesn't have + // storage info like free space / used space + } + + }); + + OCA.Trashbin.FileList = FileList; })(); + diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js deleted file mode 100644 index 5f2436de80..0000000000 --- a/apps/files_trashbin/js/trash.js +++ /dev/null @@ -1,130 +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, t, BreadCrumb, FileActions, FileList, Files */ -$(document).ready(function() { - var deletedRegExp = new RegExp(/^(.+)\.d[0-9]+$/); - - /** - * Convert a file name in the format filename.d12345 to the real file name. - * This will use basename. - * The name will not be changed if it has no ".d12345" suffix. - * @param name file name - * @return converted file name - */ - function getDeletedFileName(name) { - name = OC.basename(name); - var match = deletedRegExp.exec(name); - if (match && match.length > 1) { - name = match[1]; - } - return name; - } - - Files.updateStorageStatistics = function() { - // no op because the trashbin doesn't have - // storage info like free space / used space - }; - - if (typeof FileActions !== 'undefined') { - FileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/history'), function(filename) { - var tr = FileList.findFileEl(filename); - var deleteAction = tr.children("td.date").children(".action.delete"); - deleteAction.removeClass('delete-icon').addClass('progress-icon'); - disableActions(); - $.post(OC.filePath('files_trashbin', 'ajax', 'undelete.php'), { - files: JSON.stringify([filename]), - dir: FileList.getCurrentDirectory() - }, - FileList._removeCallback - ); - }, t('files_trashbin', 'Restore')); - }; - - FileActions.register('all', 'Delete', OC.PERMISSION_READ, function() { - return OC.imagePath('core', 'actions/delete'); - }, function(filename) { - $('.tipsy').remove(); - var tr = FileList.findFileEl(filename); - var deleteAction = tr.children("td.date").children(".action.delete"); - deleteAction.removeClass('delete-icon').addClass('progress-icon'); - disableActions(); - $.post(OC.filePath('files_trashbin', 'ajax', 'delete.php'), { - files: JSON.stringify([filename]), - dir: FileList.getCurrentDirectory() - }, - FileList._removeCallback - ); - }); - - /** - * Override crumb URL maker (hacky!) - */ - FileList.breadcrumb.getCrumbUrl = function(part, index) { - if (index === 0) { - return OC.linkTo('files', 'index.php'); - } - return OC.linkTo('files_trashbin', 'index.php')+"?dir=" + encodeURIComponent(part.dir); - }; - - Files.generatePreviewUrl = function(urlSpec) { - return OC.generateUrl('/apps/files_trashbin/ajax/preview.php?') + $.param(urlSpec); - }; - - Files.getDownloadUrl = function(action, params) { - // no downloads - return '#'; - }; - - Files.getAjaxUrl = function(action, params) { - var q = ''; - if (params) { - q = '?' + OC.buildQueryString(params); - } - return OC.filePath('files_trashbin', 'ajax', action + '.php') + q; - }; - - - /** - * Override crumb making to add "Deleted Files" entry - * and convert files with ".d" extensions to a more - * user friendly name. - */ - var oldMakeCrumbs = BreadCrumb.prototype._makeCrumbs; - BreadCrumb.prototype._makeCrumbs = function() { - var parts = oldMakeCrumbs.apply(this, arguments); - // duplicate first part - parts.unshift(parts[0]); - parts[1] = { - dir: '/', - name: t('files_trashbin', 'Deleted Files') - }; - for (var i = 2; i < parts.length; i++) { - parts[i].name = getDeletedFileName(parts[i].name); - } - return parts; - }; - - FileActions.actions.dir = { - // only keep 'Open' action for navigation - 'Open': FileActions.actions.dir.Open - }; -}); - -function enableActions() { - $(".action").css("display", "inline"); - $(":input:checkbox").css("display", "inline"); -} - -function disableActions() { - $(".action").css("display", "none"); - $(":input:checkbox").css("display", "none"); -} - diff --git a/apps/files_trashbin/l10n/ar.php b/apps/files_trashbin/l10n/ar.php index b3abc7df86..5a6105bda6 100644 --- a/apps/files_trashbin/l10n/ar.php +++ b/apps/files_trashbin/l10n/ar.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "تعذّر حذف%s بشكل دائم", "Couldn't restore %s" => "تعذّر استرجاع %s ", "Deleted files" => "حذف الملفات", +"Restore" => "استعيد", "Error" => "خطأ", -"Deleted Files" => "الملفات المحذوفه", "restored" => "تمت الاستعادة", "Nothing in here. Your trash bin is empty!" => "لا يوجد شيء هنا. سلة المهملات خاليه.", "Name" => "اسم", -"Restore" => "استعيد", "Deleted" => "تم الحذف", "Delete" => "إلغاء" ); diff --git a/apps/files_trashbin/l10n/ast.php b/apps/files_trashbin/l10n/ast.php index 688e1ce3d8..3240d6751c 100644 --- a/apps/files_trashbin/l10n/ast.php +++ b/apps/files_trashbin/l10n/ast.php @@ -2,11 +2,12 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nun pudo desaniciase %s dafechu", "Couldn't restore %s" => "Nun pudo restaurase %s", +"Deleted files" => "Ficheros desaniciaos", +"Restore" => "Restaurar", "Error" => "Fallu", -"Deleted Files" => "Ficheros desaniciaos", +"restored" => "recuperóse", "Nothing in here. Your trash bin is empty!" => "Nun hai un res equí. La papelera ta balera!", "Name" => "Nome", -"Restore" => "Restaurar", "Deleted" => "Desaniciáu", "Delete" => "Desaniciar" ); diff --git a/apps/files_trashbin/l10n/bg_BG.php b/apps/files_trashbin/l10n/bg_BG.php index 8c9e658068..62057538ce 100644 --- a/apps/files_trashbin/l10n/bg_BG.php +++ b/apps/files_trashbin/l10n/bg_BG.php @@ -2,11 +2,10 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Невъзможно перманентното изтриване на %s", "Couldn't restore %s" => "Невъзможно възтановяване на %s", +"Restore" => "Възтановяване", "Error" => "Грешка", -"Deleted Files" => "Изтрити файлове", "Nothing in here. Your trash bin is empty!" => "Няма нищо. Кофата е празна!", "Name" => "Име", -"Restore" => "Възтановяване", "Deleted" => "Изтрито", "Delete" => "Изтриване" ); diff --git a/apps/files_trashbin/l10n/ca.php b/apps/files_trashbin/l10n/ca.php index 196d6ac00a..59b42797cf 100644 --- a/apps/files_trashbin/l10n/ca.php +++ b/apps/files_trashbin/l10n/ca.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "No s'ha pogut esborrar permanentment %s", "Couldn't restore %s" => "No s'ha pogut restaurar %s", "Deleted files" => "Fitxers esborrats", +"Restore" => "Recupera", "Error" => "Error", -"Deleted Files" => "Fitxers eliminats", "restored" => "restaurat", "Nothing in here. Your trash bin is empty!" => "La paperera està buida!", "Name" => "Nom", -"Restore" => "Recupera", "Deleted" => "Eliminat", "Delete" => "Esborra" ); diff --git a/apps/files_trashbin/l10n/cs_CZ.php b/apps/files_trashbin/l10n/cs_CZ.php index ed795582e4..3e4f9e0e15 100644 --- a/apps/files_trashbin/l10n/cs_CZ.php +++ b/apps/files_trashbin/l10n/cs_CZ.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nelze trvale odstranit %s", "Couldn't restore %s" => "Nelze obnovit %s", "Deleted files" => "Odstraněné soubory", +"Restore" => "Obnovit", "Error" => "Chyba", -"Deleted Files" => "Smazané soubory", "restored" => "obnoveno", "Nothing in here. Your trash bin is empty!" => "Žádný obsah. Váš koš je prázdný.", "Name" => "Název", -"Restore" => "Obnovit", "Deleted" => "Smazáno", "Delete" => "Smazat" ); diff --git a/apps/files_trashbin/l10n/cy_GB.php b/apps/files_trashbin/l10n/cy_GB.php index 7b1405777d..4e76a6d25a 100644 --- a/apps/files_trashbin/l10n/cy_GB.php +++ b/apps/files_trashbin/l10n/cy_GB.php @@ -3,11 +3,10 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Methwyd dileu %s yn barhaol", "Couldn't restore %s" => "Methwyd adfer %s", "Deleted files" => "Ffeiliau ddilewyd", +"Restore" => "Adfer", "Error" => "Gwall", -"Deleted Files" => "Ffeiliau Ddilewyd", "Nothing in here. Your trash bin is empty!" => "Does dim byd yma. Mae eich bin sbwriel yn wag!", "Name" => "Enw", -"Restore" => "Adfer", "Deleted" => "Wedi dileu", "Delete" => "Dileu" ); diff --git a/apps/files_trashbin/l10n/da.php b/apps/files_trashbin/l10n/da.php index 7f7b65bca2..b651d81d1b 100644 --- a/apps/files_trashbin/l10n/da.php +++ b/apps/files_trashbin/l10n/da.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Kunne ikke slette %s permanent", "Couldn't restore %s" => "Kunne ikke gendanne %s", "Deleted files" => "Slettede filer", +"Restore" => "Gendan", "Error" => "Fejl", -"Deleted Files" => "Slettede filer", "restored" => "Gendannet", "Nothing in here. Your trash bin is empty!" => "Intet at se her. Din papirkurv er tom!", "Name" => "Navn", -"Restore" => "Gendan", "Deleted" => "Slettet", "Delete" => "Slet" ); diff --git a/apps/files_trashbin/l10n/de.php b/apps/files_trashbin/l10n/de.php index 4778e159e1..56b7ccfc7b 100644 --- a/apps/files_trashbin/l10n/de.php +++ b/apps/files_trashbin/l10n/de.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Konnte %s nicht dauerhaft löschen", "Couldn't restore %s" => "Konnte %s nicht wiederherstellen", "Deleted files" => "Gelöschte Dateien", +"Restore" => "Wiederherstellen", "Error" => "Fehler", -"Deleted Files" => "Gelöschte Dateien", "restored" => "Wiederhergestellt", "Nothing in here. Your trash bin is empty!" => "Nichts zu löschen, der Papierkorb ist leer!", "Name" => "Name", -"Restore" => "Wiederherstellen", "Deleted" => "gelöscht", "Delete" => "Löschen" ); diff --git a/apps/files_trashbin/l10n/de_CH.php b/apps/files_trashbin/l10n/de_CH.php index 603d82f5c7..be54e57d3f 100644 --- a/apps/files_trashbin/l10n/de_CH.php +++ b/apps/files_trashbin/l10n/de_CH.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Konnte %s nicht dauerhaft löschen", "Couldn't restore %s" => "Konnte %s nicht wiederherstellen", "Deleted files" => "Gelöschte Dateien", +"Restore" => "Wiederherstellen", "Error" => "Fehler", -"Deleted Files" => "Gelöschte Dateien", "restored" => "Wiederhergestellt", "Nothing in here. Your trash bin is empty!" => "Nichts zu löschen, Ihr Papierkorb ist leer!", "Name" => "Name", -"Restore" => "Wiederherstellen", "Deleted" => "Gelöscht", "Delete" => "Löschen" ); diff --git a/apps/files_trashbin/l10n/de_DE.php b/apps/files_trashbin/l10n/de_DE.php index 603d82f5c7..be54e57d3f 100644 --- a/apps/files_trashbin/l10n/de_DE.php +++ b/apps/files_trashbin/l10n/de_DE.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Konnte %s nicht dauerhaft löschen", "Couldn't restore %s" => "Konnte %s nicht wiederherstellen", "Deleted files" => "Gelöschte Dateien", +"Restore" => "Wiederherstellen", "Error" => "Fehler", -"Deleted Files" => "Gelöschte Dateien", "restored" => "Wiederhergestellt", "Nothing in here. Your trash bin is empty!" => "Nichts zu löschen, Ihr Papierkorb ist leer!", "Name" => "Name", -"Restore" => "Wiederherstellen", "Deleted" => "Gelöscht", "Delete" => "Löschen" ); diff --git a/apps/files_trashbin/l10n/el.php b/apps/files_trashbin/l10n/el.php index 23b23ed93a..c77bfb7fa1 100644 --- a/apps/files_trashbin/l10n/el.php +++ b/apps/files_trashbin/l10n/el.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Αδύνατη η μόνιμη διαγραφή του %s", "Couldn't restore %s" => "Αδυναμία επαναφοράς %s", "Deleted files" => "Διαγραμμένα αρχεία", +"Restore" => "Επαναφορά", "Error" => "Σφάλμα", -"Deleted Files" => "Διαγραμμένα Αρχεία", "restored" => "επαναφέρθηκαν", "Nothing in here. Your trash bin is empty!" => "Δεν υπάρχει τίποτα εδώ. Ο κάδος σας είναι άδειος!", "Name" => "Όνομα", -"Restore" => "Επαναφορά", "Deleted" => "Διαγραμμένα", "Delete" => "Διαγραφή" ); diff --git a/apps/files_trashbin/l10n/en_GB.php b/apps/files_trashbin/l10n/en_GB.php index a660b4b1ca..b2715dfceb 100644 --- a/apps/files_trashbin/l10n/en_GB.php +++ b/apps/files_trashbin/l10n/en_GB.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Couldn't delete %s permanently", "Couldn't restore %s" => "Couldn't restore %s", "Deleted files" => "Deleted files", +"Restore" => "Restore", "Error" => "Error", -"Deleted Files" => "Deleted Files", "restored" => "restored", "Nothing in here. Your trash bin is empty!" => "Nothing in here. Your recycle bin is empty!", "Name" => "Name", -"Restore" => "Restore", "Deleted" => "Deleted", "Delete" => "Delete" ); diff --git a/apps/files_trashbin/l10n/eo.php b/apps/files_trashbin/l10n/eo.php index d644f0f642..67617f448d 100644 --- a/apps/files_trashbin/l10n/eo.php +++ b/apps/files_trashbin/l10n/eo.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Ne povis foriĝi %s por ĉiam", "Couldn't restore %s" => "Ne povis restaŭriĝi %s", "Deleted files" => "Forigitaj dosieroj", +"Restore" => "Restaŭri", "Error" => "Eraro", -"Deleted Files" => "Forigitaj dosieroj", "restored" => "restaŭrita", "Nothing in here. Your trash bin is empty!" => "Nenio estas ĉi tie. Via rubujo malplenas!", "Name" => "Nomo", -"Restore" => "Restaŭri", "Deleted" => "Forigita", "Delete" => "Forigi" ); diff --git a/apps/files_trashbin/l10n/es.php b/apps/files_trashbin/l10n/es.php index c0dc6bb45c..c3db776515 100644 --- a/apps/files_trashbin/l10n/es.php +++ b/apps/files_trashbin/l10n/es.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "No se puede eliminar %s permanentemente", "Couldn't restore %s" => "No se puede restaurar %s", "Deleted files" => "Archivos eliminados", +"Restore" => "Recuperar", "Error" => "Error", -"Deleted Files" => "Archivos Eliminados", "restored" => "recuperado", "Nothing in here. Your trash bin is empty!" => "No hay nada aquí. ¡Tu papelera esta vacía!", "Name" => "Nombre", -"Restore" => "Recuperar", "Deleted" => "Eliminado", "Delete" => "Eliminar" ); diff --git a/apps/files_trashbin/l10n/es_AR.php b/apps/files_trashbin/l10n/es_AR.php index b354dd656b..2991ea507b 100644 --- a/apps/files_trashbin/l10n/es_AR.php +++ b/apps/files_trashbin/l10n/es_AR.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "No fue posible borrar %s de manera permanente", "Couldn't restore %s" => "No se pudo restaurar %s", "Deleted files" => "Archivos borrados", +"Restore" => "Recuperar", "Error" => "Error", -"Deleted Files" => "Archivos eliminados", "restored" => "recuperado", "Nothing in here. Your trash bin is empty!" => "No hay nada acá. ¡La papelera está vacía!", "Name" => "Nombre", -"Restore" => "Recuperar", "Deleted" => "Borrado", "Delete" => "Borrar" ); diff --git a/apps/files_trashbin/l10n/es_MX.php b/apps/files_trashbin/l10n/es_MX.php index c0dc6bb45c..c3db776515 100644 --- a/apps/files_trashbin/l10n/es_MX.php +++ b/apps/files_trashbin/l10n/es_MX.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "No se puede eliminar %s permanentemente", "Couldn't restore %s" => "No se puede restaurar %s", "Deleted files" => "Archivos eliminados", +"Restore" => "Recuperar", "Error" => "Error", -"Deleted Files" => "Archivos Eliminados", "restored" => "recuperado", "Nothing in here. Your trash bin is empty!" => "No hay nada aquí. ¡Tu papelera esta vacía!", "Name" => "Nombre", -"Restore" => "Recuperar", "Deleted" => "Eliminado", "Delete" => "Eliminar" ); diff --git a/apps/files_trashbin/l10n/et_EE.php b/apps/files_trashbin/l10n/et_EE.php index 69d20cb195..c1c9ea66c4 100644 --- a/apps/files_trashbin/l10n/et_EE.php +++ b/apps/files_trashbin/l10n/et_EE.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "%s jäädavalt kustutamine ebaõnnestus", "Couldn't restore %s" => "%s ei saa taastada", "Deleted files" => "Kustutatud failid", +"Restore" => "Taasta", "Error" => "Viga", -"Deleted Files" => "Kustutatud failid", "restored" => "taastatud", "Nothing in here. Your trash bin is empty!" => "Siin pole midagi. Sinu prügikast on tühi!", "Name" => "Nimi", -"Restore" => "Taasta", "Deleted" => "Kustutatud", "Delete" => "Kustuta" ); diff --git a/apps/files_trashbin/l10n/eu.php b/apps/files_trashbin/l10n/eu.php index 42476bccfe..63c1245da0 100644 --- a/apps/files_trashbin/l10n/eu.php +++ b/apps/files_trashbin/l10n/eu.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Ezin izan da %s betirako ezabatu", "Couldn't restore %s" => "Ezin izan da %s berreskuratu", "Deleted files" => "Ezabatutako fitxategiak", +"Restore" => "Berrezarri", "Error" => "Errorea", -"Deleted Files" => "Ezabatutako Fitxategiak", "restored" => "Berrezarrita", "Nothing in here. Your trash bin is empty!" => "Ez dago ezer ez. Zure zakarrontzia hutsik dago!", "Name" => "Izena", -"Restore" => "Berrezarri", "Deleted" => "Ezabatuta", "Delete" => "Ezabatu" ); diff --git a/apps/files_trashbin/l10n/fa.php b/apps/files_trashbin/l10n/fa.php index 407524eb62..0823e98ea1 100644 --- a/apps/files_trashbin/l10n/fa.php +++ b/apps/files_trashbin/l10n/fa.php @@ -3,11 +3,10 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "%s را نمی توان برای همیشه حذف کرد", "Couldn't restore %s" => "%s را نمی توان بازگرداند", "Deleted files" => "فایل های حذف شده", +"Restore" => "بازیابی", "Error" => "خطا", -"Deleted Files" => "فایلهای حذف شده", "Nothing in here. Your trash bin is empty!" => "هیچ چیزی اینجا نیست. سطل زباله ی شما خالی است.", "Name" => "نام", -"Restore" => "بازیابی", "Deleted" => "حذف شده", "Delete" => "حذف" ); diff --git a/apps/files_trashbin/l10n/fi_FI.php b/apps/files_trashbin/l10n/fi_FI.php index da56baf0bd..158fc7dac5 100644 --- a/apps/files_trashbin/l10n/fi_FI.php +++ b/apps/files_trashbin/l10n/fi_FI.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Kohdetta %s ei voitu poistaa pysyvästi", "Couldn't restore %s" => "Kohteen %s palautus epäonnistui", "Deleted files" => "Poistetut tiedostot", +"Restore" => "Palauta", "Error" => "Virhe", -"Deleted Files" => "Poistetut tiedostot", "restored" => "palautettu", "Nothing in here. Your trash bin is empty!" => "Tyhjää täynnä! Roskakorissa ei ole mitään.", "Name" => "Nimi", -"Restore" => "Palauta", "Deleted" => "Poistettu", "Delete" => "Poista" ); diff --git a/apps/files_trashbin/l10n/fr.php b/apps/files_trashbin/l10n/fr.php index b71fbea96a..0e6330bb2d 100644 --- a/apps/files_trashbin/l10n/fr.php +++ b/apps/files_trashbin/l10n/fr.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Impossible d'effacer %s de façon permanente", "Couldn't restore %s" => "Impossible de restaurer %s", "Deleted files" => "Fichiers supprimés", +"Restore" => "Restaurer", "Error" => "Erreur", -"Deleted Files" => "Fichiers effacés", "restored" => "restauré", "Nothing in here. Your trash bin is empty!" => "Il n'y a rien ici. Votre corbeille est vide !", "Name" => "Nom", -"Restore" => "Restaurer", "Deleted" => "Effacé", "Delete" => "Supprimer" ); diff --git a/apps/files_trashbin/l10n/gl.php b/apps/files_trashbin/l10n/gl.php index fe74ab34a0..143cf0e6df 100644 --- a/apps/files_trashbin/l10n/gl.php +++ b/apps/files_trashbin/l10n/gl.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Non foi posíbel eliminar %s permanente", "Couldn't restore %s" => "Non foi posíbel restaurar %s", "Deleted files" => "Ficheiros eliminados", +"Restore" => "Restablecer", "Error" => "Erro", -"Deleted Files" => "Ficheiros eliminados", "restored" => "restaurado", "Nothing in here. Your trash bin is empty!" => "Aquí non hai nada. O cesto do lixo está baleiro!", "Name" => "Nome", -"Restore" => "Restablecer", "Deleted" => "Eliminado", "Delete" => "Eliminar" ); diff --git a/apps/files_trashbin/l10n/he.php b/apps/files_trashbin/l10n/he.php index 6cdc5c05c9..90b3fd11ab 100644 --- a/apps/files_trashbin/l10n/he.php +++ b/apps/files_trashbin/l10n/he.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "לא ניתן למחוק את %s לצמיתות", "Couldn't restore %s" => "לא ניתן לשחזר את %s", "Deleted files" => "קבצים שנמחקו", +"Restore" => "שחזור", "Error" => "שגיאה", -"Deleted Files" => "קבצים שנמחקו", "restored" => "שוחזר", "Nothing in here. Your trash bin is empty!" => "אין כאן שום דבר. סל המיחזור שלך ריק!", "Name" => "שם", -"Restore" => "שחזור", "Deleted" => "נמחק", "Delete" => "מחיקה" ); diff --git a/apps/files_trashbin/l10n/hu_HU.php b/apps/files_trashbin/l10n/hu_HU.php index 2912821d96..60f3ebad85 100644 --- a/apps/files_trashbin/l10n/hu_HU.php +++ b/apps/files_trashbin/l10n/hu_HU.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nem sikerült %s végleges törlése", "Couldn't restore %s" => "Nem sikerült %s visszaállítása", "Deleted files" => "Törölt fájlok", +"Restore" => "Visszaállítás", "Error" => "Hiba", -"Deleted Files" => "Törölt fájlok", "restored" => "visszaállítva", "Nothing in here. Your trash bin is empty!" => "Itt nincs semmi. Az Ön szemetes mappája üres!", "Name" => "Név", -"Restore" => "Visszaállítás", "Deleted" => "Törölve", "Delete" => "Törlés" ); diff --git a/apps/files_trashbin/l10n/id.php b/apps/files_trashbin/l10n/id.php index 166b9aa811..bba9e329ee 100644 --- a/apps/files_trashbin/l10n/id.php +++ b/apps/files_trashbin/l10n/id.php @@ -3,11 +3,10 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Tidak dapat menghapus permanen %s", "Couldn't restore %s" => "Tidak dapat memulihkan %s", "Deleted files" => "Berkas yang dihapus", +"Restore" => "Pulihkan", "Error" => "Galat", -"Deleted Files" => "Berkas yang Dihapus", "Nothing in here. Your trash bin is empty!" => "Tempat sampah anda kosong!", "Name" => "Nama", -"Restore" => "Pulihkan", "Deleted" => "Dihapus", "Delete" => "Hapus" ); diff --git a/apps/files_trashbin/l10n/it.php b/apps/files_trashbin/l10n/it.php index 057305ac51..905384b82b 100644 --- a/apps/files_trashbin/l10n/it.php +++ b/apps/files_trashbin/l10n/it.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Impossibile eliminare %s definitivamente", "Couldn't restore %s" => "Impossibile ripristinare %s", "Deleted files" => "File eliminati", +"Restore" => "Ripristina", "Error" => "Errore", -"Deleted Files" => "File eliminati", "restored" => "ripristinati", "Nothing in here. Your trash bin is empty!" => "Qui non c'è niente. Il tuo cestino è vuoto.", "Name" => "Nome", -"Restore" => "Ripristina", "Deleted" => "Eliminati", "Delete" => "Elimina" ); diff --git a/apps/files_trashbin/l10n/ja.php b/apps/files_trashbin/l10n/ja.php index 13ca95e6fb..b24e40aa23 100644 --- a/apps/files_trashbin/l10n/ja.php +++ b/apps/files_trashbin/l10n/ja.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "%s を完全に削除できませんでした", "Couldn't restore %s" => "%s を復元できませんでした", "Deleted files" => "ゴミ箱", +"Restore" => "復元", "Error" => "エラー", -"Deleted Files" => "ゴミ箱", "restored" => "復元済", "Nothing in here. Your trash bin is empty!" => "ここには何もありません。ゴミ箱は空です!", "Name" => "名前", -"Restore" => "復元", "Deleted" => "削除済み", "Delete" => "削除" ); diff --git a/apps/files_trashbin/l10n/ka_GE.php b/apps/files_trashbin/l10n/ka_GE.php index 4e3ad4260e..16e147bd41 100644 --- a/apps/files_trashbin/l10n/ka_GE.php +++ b/apps/files_trashbin/l10n/ka_GE.php @@ -3,11 +3,10 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "ფაილი %s–ის სრულად წაშლა ვერ მოხერხდა", "Couldn't restore %s" => "%s–ის აღდგენა ვერ მოხერხდა", "Deleted files" => "წაშლილი ფაილები", +"Restore" => "აღდგენა", "Error" => "შეცდომა", -"Deleted Files" => "წაშლილი ფაილები", "Nothing in here. Your trash bin is empty!" => "აქ არაფერი არ არის. სანაგვე ყუთი ცარიელია!", "Name" => "სახელი", -"Restore" => "აღდგენა", "Deleted" => "წაშლილი", "Delete" => "წაშლა" ); diff --git a/apps/files_trashbin/l10n/km.php b/apps/files_trashbin/l10n/km.php index 1df805de2d..40119afc87 100644 --- a/apps/files_trashbin/l10n/km.php +++ b/apps/files_trashbin/l10n/km.php @@ -1,8 +1,14 @@ "កំហុស", -"Name" => "ឈ្មោះ", +"Couldn't delete %s permanently" => "មិន​អាច​លុប %s ចោល​ជា​អចិន្ត្រៃយ៍​ទេ", +"Couldn't restore %s" => "មិន​អាច​ស្ដារ %s ឡើង​វិញ​បាន​ទេ", +"Deleted files" => "ឯកសារ​ដែល​បាន​លុប", "Restore" => "ស្ដារ​មក​វិញ", +"Error" => "កំហុស", +"restored" => "បាន​ស្ដារ​វិញ", +"Nothing in here. Your trash bin is empty!" => "គ្មាន​អ្វី​នៅ​ទីនេះ​ទេ។ ធុង​សំរាម​របស់​អ្នក​គឺ​ទទេ!", +"Name" => "ឈ្មោះ", +"Deleted" => "បាន​លុប", "Delete" => "លុប" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/apps/files_trashbin/l10n/ko.php b/apps/files_trashbin/l10n/ko.php index d9d8707080..98800fd2e5 100644 --- a/apps/files_trashbin/l10n/ko.php +++ b/apps/files_trashbin/l10n/ko.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "%s을(를_ 영구적으로 삭제할 수 없습니다", "Couldn't restore %s" => "%s을(를) 복원할 수 없습니다", "Deleted files" => "삭제된 파일", +"Restore" => "복원", "Error" => "오류", -"Deleted Files" => "삭제된 파일", "restored" => "복원됨", "Nothing in here. Your trash bin is empty!" => "휴지통이 비어 있습니다!", "Name" => "이름", -"Restore" => "복원", "Deleted" => "삭제됨", "Delete" => "삭제" ); diff --git a/apps/files_trashbin/l10n/lt_LT.php b/apps/files_trashbin/l10n/lt_LT.php index 2bf545483f..fa65d7eaba 100644 --- a/apps/files_trashbin/l10n/lt_LT.php +++ b/apps/files_trashbin/l10n/lt_LT.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nepavyko negrįžtamai ištrinti %s", "Couldn't restore %s" => "Nepavyko atkurti %s", "Deleted files" => "Ištrinti failai", +"Restore" => "Atstatyti", "Error" => "Klaida", -"Deleted Files" => "Ištrinti failai", "restored" => "atstatyta", "Nothing in here. Your trash bin is empty!" => "Nieko nėra. Jūsų šiukšliadėžė tuščia!", "Name" => "Pavadinimas", -"Restore" => "Atstatyti", "Deleted" => "Ištrinti", "Delete" => "Ištrinti" ); diff --git a/apps/files_trashbin/l10n/lv.php b/apps/files_trashbin/l10n/lv.php index c173d05014..3432f9ac75 100644 --- a/apps/files_trashbin/l10n/lv.php +++ b/apps/files_trashbin/l10n/lv.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nevarēja pilnībā izdzēst %s", "Couldn't restore %s" => "Nevarēja atjaunot %s", "Deleted files" => "Dzēstās datnes", +"Restore" => "Atjaunot", "Error" => "Kļūda", -"Deleted Files" => "Dzēstās datnes", "restored" => "atjaunots", "Nothing in here. Your trash bin is empty!" => "Šeit nekā nav. Jūsu miskaste ir tukša!", "Name" => "Nosaukums", -"Restore" => "Atjaunot", "Deleted" => "Dzēsts", "Delete" => "Dzēst" ); diff --git a/apps/files_trashbin/l10n/mk.php b/apps/files_trashbin/l10n/mk.php index 910b11e21e..66c2d0a296 100644 --- a/apps/files_trashbin/l10n/mk.php +++ b/apps/files_trashbin/l10n/mk.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Не можеше трајно да се избрише %s", "Couldn't restore %s" => "Не можеше да се поврати %s", "Deleted files" => "Избришани датотеки", +"Restore" => "Поврати", "Error" => "Грешка", -"Deleted Files" => "Избришани датотеки", "restored" => "повратени", "Nothing in here. Your trash bin is empty!" => "Тука нема ништо. Вашата корпа за отпадоци е празна!", "Name" => "Име", -"Restore" => "Поврати", "Deleted" => "Избришан", "Delete" => "Избриши" ); diff --git a/apps/files_trashbin/l10n/ms_MY.php b/apps/files_trashbin/l10n/ms_MY.php index f084f58465..fdfd922438 100644 --- a/apps/files_trashbin/l10n/ms_MY.php +++ b/apps/files_trashbin/l10n/ms_MY.php @@ -2,12 +2,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Tidak dapat menghapuskan %s secara kekal", "Couldn't restore %s" => "Tidak dapat memulihkan %s", +"Restore" => "Pulihkan", "Error" => "Ralat", -"Deleted Files" => "Fail Dihapus", "restored" => "dipulihkan", "Nothing in here. Your trash bin is empty!" => "Tiada apa disini. Tong sampah anda kosong!", "Name" => "Nama", -"Restore" => "Pulihkan", "Deleted" => "Dihapuskan", "Delete" => "Padam" ); diff --git a/apps/files_trashbin/l10n/nb_NO.php b/apps/files_trashbin/l10n/nb_NO.php index 2293e5a4e7..519b4e5aa2 100644 --- a/apps/files_trashbin/l10n/nb_NO.php +++ b/apps/files_trashbin/l10n/nb_NO.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Kunne ikke slette %s fullstendig", "Couldn't restore %s" => "Kunne ikke gjenopprette %s", "Deleted files" => "Slettede filer", +"Restore" => "Gjenopprett", "Error" => "Feil", -"Deleted Files" => "Slettede filer", "restored" => "gjenopprettet", "Nothing in here. Your trash bin is empty!" => "Ingenting her. Søppelkassen din er tom!", "Name" => "Navn", -"Restore" => "Gjenopprett", "Deleted" => "Slettet", "Delete" => "Slett" ); diff --git a/apps/files_trashbin/l10n/nl.php b/apps/files_trashbin/l10n/nl.php index c8fb128853..41dfa86b7a 100644 --- a/apps/files_trashbin/l10n/nl.php +++ b/apps/files_trashbin/l10n/nl.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Kon %s niet permanent verwijderen", "Couldn't restore %s" => "Kon %s niet herstellen", "Deleted files" => "Verwijderde bestanden", +"Restore" => "Herstellen", "Error" => "Fout", -"Deleted Files" => "Verwijderde bestanden", "restored" => "hersteld", "Nothing in here. Your trash bin is empty!" => "Niets te vinden. Uw prullenbak is leeg!", "Name" => "Naam", -"Restore" => "Herstellen", "Deleted" => "Verwijderd", "Delete" => "Verwijder" ); diff --git a/apps/files_trashbin/l10n/nn_NO.php b/apps/files_trashbin/l10n/nn_NO.php index 38bc64e6ce..aa18927b1f 100644 --- a/apps/files_trashbin/l10n/nn_NO.php +++ b/apps/files_trashbin/l10n/nn_NO.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Klarte ikkje sletta %s for godt", "Couldn't restore %s" => "Klarte ikkje gjenoppretta %s", "Deleted files" => "Sletta filer", +"Restore" => "Gjenopprett", "Error" => "Feil", -"Deleted Files" => "Sletta filer", "restored" => "gjenoppretta", "Nothing in here. Your trash bin is empty!" => "Ingenting her. Papirkorga di er tom!", "Name" => "Namn", -"Restore" => "Gjenopprett", "Deleted" => "Sletta", "Delete" => "Slett" ); diff --git a/apps/files_trashbin/l10n/pl.php b/apps/files_trashbin/l10n/pl.php index b961efd7da..16bb9dbfa2 100644 --- a/apps/files_trashbin/l10n/pl.php +++ b/apps/files_trashbin/l10n/pl.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nie można trwale usunąć %s", "Couldn't restore %s" => "Nie można przywrócić %s", "Deleted files" => "Pliki usunięte", +"Restore" => "Przywróć", "Error" => "Błąd", -"Deleted Files" => "Usunięte pliki", "restored" => "przywrócony", "Nothing in here. Your trash bin is empty!" => "Nic tu nie ma. Twój kosz jest pusty!", "Name" => "Nazwa", -"Restore" => "Przywróć", "Deleted" => "Usunięte", "Delete" => "Usuń" ); diff --git a/apps/files_trashbin/l10n/pt_BR.php b/apps/files_trashbin/l10n/pt_BR.php index d524d8879e..b7dd346b40 100644 --- a/apps/files_trashbin/l10n/pt_BR.php +++ b/apps/files_trashbin/l10n/pt_BR.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Não foi possível excluir %s permanentemente", "Couldn't restore %s" => "Não foi possível restaurar %s", "Deleted files" => "Arquivos apagados", +"Restore" => "Restaurar", "Error" => "Erro", -"Deleted Files" => "Arquivos Apagados", "restored" => "restaurado", "Nothing in here. Your trash bin is empty!" => "Nada aqui. Sua lixeira está vazia!", "Name" => "Nome", -"Restore" => "Restaurar", "Deleted" => "Excluído", "Delete" => "Excluir" ); diff --git a/apps/files_trashbin/l10n/pt_PT.php b/apps/files_trashbin/l10n/pt_PT.php index 94dd0eb707..8a18d842c9 100644 --- a/apps/files_trashbin/l10n/pt_PT.php +++ b/apps/files_trashbin/l10n/pt_PT.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Não foi possível eliminar %s de forma permanente", "Couldn't restore %s" => "Não foi possível restaurar %s", "Deleted files" => "Ficheiros eliminados", +"Restore" => "Restaurar", "Error" => "Erro", -"Deleted Files" => "Ficheiros Apagados", "restored" => "Restaurado", "Nothing in here. Your trash bin is empty!" => "Não hà ficheiros. O lixo está vazio!", "Name" => "Nome", -"Restore" => "Restaurar", "Deleted" => "Apagado", "Delete" => "Eliminar" ); diff --git a/apps/files_trashbin/l10n/ru.php b/apps/files_trashbin/l10n/ru.php index d10369b9ca..8d00e08241 100644 --- a/apps/files_trashbin/l10n/ru.php +++ b/apps/files_trashbin/l10n/ru.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "%s не может быть удалён навсегда", "Couldn't restore %s" => "%s не может быть восстановлен", "Deleted files" => "Удалённые файлы", +"Restore" => "Восстановить", "Error" => "Ошибка", -"Deleted Files" => "Удаленные файлы", "restored" => "восстановлен", "Nothing in here. Your trash bin is empty!" => "Здесь ничего нет. Ваша корзина пуста!", "Name" => "Имя", -"Restore" => "Восстановить", "Deleted" => "Удалён", "Delete" => "Удалить" ); diff --git a/apps/files_trashbin/l10n/sk_SK.php b/apps/files_trashbin/l10n/sk_SK.php index 3badd3a423..7588b555d9 100644 --- a/apps/files_trashbin/l10n/sk_SK.php +++ b/apps/files_trashbin/l10n/sk_SK.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nemožno zmazať %s navždy", "Couldn't restore %s" => "Nemožno obnoviť %s", "Deleted files" => "Zmazané súbory", +"Restore" => "Obnoviť", "Error" => "Chyba", -"Deleted Files" => "Zmazané súbory", "restored" => "obnovené", "Nothing in here. Your trash bin is empty!" => "Žiadny obsah. Kôš je prázdny!", "Name" => "Názov", -"Restore" => "Obnoviť", "Deleted" => "Zmazané", "Delete" => "Zmazať" ); diff --git a/apps/files_trashbin/l10n/sl.php b/apps/files_trashbin/l10n/sl.php index 08da9b1c6e..f9dc5112ac 100644 --- a/apps/files_trashbin/l10n/sl.php +++ b/apps/files_trashbin/l10n/sl.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Datoteke %s ni mogoče trajno izbrisati.", "Couldn't restore %s" => "Ni mogoče obnoviti %s", "Deleted files" => "Izbrisane datoteke", +"Restore" => "Obnovi", "Error" => "Napaka", -"Deleted Files" => "Izbrisane datoteke", "restored" => "obnovljeno", "Nothing in here. Your trash bin is empty!" => "Mapa smeti je prazna.", "Name" => "Ime", -"Restore" => "Obnovi", "Deleted" => "Izbrisano", "Delete" => "Izbriši" ); diff --git a/apps/files_trashbin/l10n/sq.php b/apps/files_trashbin/l10n/sq.php index 60d16f9b91..9e16b7a7bf 100644 --- a/apps/files_trashbin/l10n/sq.php +++ b/apps/files_trashbin/l10n/sq.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Nuk munda ta eliminoj përfundimisht %s", "Couldn't restore %s" => "Nuk munda ta rivendos %s", "Deleted files" => "Skedarë të fshirë ", +"Restore" => "Rivendos", "Error" => "Veprim i gabuar", -"Deleted Files" => "Skedarë të eliminuar", "restored" => "rivendosur", "Nothing in here. Your trash bin is empty!" => "Këtu nuk ka asgjë. Koshi juaj është bosh!", "Name" => "Emri", -"Restore" => "Rivendos", "Deleted" => "Eliminuar", "Delete" => "Elimino" ); diff --git a/apps/files_trashbin/l10n/sr.php b/apps/files_trashbin/l10n/sr.php index 7fb4c85ab6..d4abc908c9 100644 --- a/apps/files_trashbin/l10n/sr.php +++ b/apps/files_trashbin/l10n/sr.php @@ -1,10 +1,10 @@ "Обрисане датотеке", +"Restore" => "Врати", "Error" => "Грешка", "Nothing in here. Your trash bin is empty!" => "Овде нема ништа. Корпа за отпатке је празна.", "Name" => "Име", -"Restore" => "Врати", "Deleted" => "Обрисано", "Delete" => "Обриши" ); diff --git a/apps/files_trashbin/l10n/sv.php b/apps/files_trashbin/l10n/sv.php index fd9ca8653f..330bcc3482 100644 --- a/apps/files_trashbin/l10n/sv.php +++ b/apps/files_trashbin/l10n/sv.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Kunde inte radera %s permanent", "Couldn't restore %s" => "Kunde inte återställa %s", "Deleted files" => "Raderade filer", +"Restore" => "Återskapa", "Error" => "Fel", -"Deleted Files" => "Raderade filer", "restored" => "återställd", "Nothing in here. Your trash bin is empty!" => "Ingenting här. Din papperskorg är tom!", "Name" => "Namn", -"Restore" => "Återskapa", "Deleted" => "Raderad", "Delete" => "Radera" ); diff --git a/apps/files_trashbin/l10n/th_TH.php b/apps/files_trashbin/l10n/th_TH.php index 857737c59e..47c3450d2e 100644 --- a/apps/files_trashbin/l10n/th_TH.php +++ b/apps/files_trashbin/l10n/th_TH.php @@ -1,10 +1,9 @@ "คืนค่า", "Error" => "ข้อผิดพลาด", -"Deleted Files" => "ไฟล์ที่ลบทิ้ง", "Nothing in here. Your trash bin is empty!" => "ไม่มีอะไรอยู่ในนี้ ถังขยะของคุณยังว่างอยู่", "Name" => "ชื่อ", -"Restore" => "คืนค่า", "Deleted" => "ลบแล้ว", "Delete" => "ลบ" ); diff --git a/apps/files_trashbin/l10n/tr.php b/apps/files_trashbin/l10n/tr.php index ff4227e38c..ab7441b822 100644 --- a/apps/files_trashbin/l10n/tr.php +++ b/apps/files_trashbin/l10n/tr.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "%s alıcı olarak silinemedi", "Couldn't restore %s" => "%s geri yüklenemedi", "Deleted files" => "Silinmiş dosyalar", +"Restore" => "Geri yükle", "Error" => "Hata", -"Deleted Files" => "Silinen Dosyalar", "restored" => "geri yüklendi", "Nothing in here. Your trash bin is empty!" => "Burada hiçbir şey yok. Çöp kutunuz tamamen boş!", "Name" => "İsim", -"Restore" => "Geri yükle", "Deleted" => "Silindi", "Delete" => "Sil" ); diff --git a/apps/files_trashbin/l10n/uk.php b/apps/files_trashbin/l10n/uk.php index fa523fa321..328e8da5e0 100644 --- a/apps/files_trashbin/l10n/uk.php +++ b/apps/files_trashbin/l10n/uk.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Неможливо видалити %s назавжди", "Couldn't restore %s" => "Неможливо відновити %s", "Deleted files" => "Видалено файлів", +"Restore" => "Відновити", "Error" => "Помилка", -"Deleted Files" => "Видалено Файлів", "restored" => "відновлено", "Nothing in here. Your trash bin is empty!" => "Нічого немає. Ваший кошик для сміття пустий!", "Name" => "Ім'я", -"Restore" => "Відновити", "Deleted" => "Видалено", "Delete" => "Видалити" ); diff --git a/apps/files_trashbin/l10n/ur_PK.php b/apps/files_trashbin/l10n/ur_PK.php index 49c82f5387..fc71b528ce 100644 --- a/apps/files_trashbin/l10n/ur_PK.php +++ b/apps/files_trashbin/l10n/ur_PK.php @@ -1,5 +1,14 @@ "ایرر" +"Couldn't delete %s permanently" => "حذف نہیں ہو سکتا %s مستقل طور پر", +"Couldn't restore %s" => "بحال نہيں کيا جا سکتا %s", +"Deleted files" => "حذف شدہ فائليں", +"Restore" => "بحال", +"Error" => "ایرر", +"restored" => "بحال شدہ", +"Nothing in here. Your trash bin is empty!" => " یہاں کچھ بھی نہیں .آپکی ردی کی ٹوکری خالی ہے.", +"Name" => "اسم", +"Deleted" => "حذف شدہ ", +"Delete" => "حذف کریں" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/apps/files_trashbin/l10n/vi.php b/apps/files_trashbin/l10n/vi.php index 57c82cea5f..d374effcab 100644 --- a/apps/files_trashbin/l10n/vi.php +++ b/apps/files_trashbin/l10n/vi.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "Không thể xóa %s vĩnh viễn", "Couldn't restore %s" => "Không thể khôi phục %s", "Deleted files" => "File đã bị xóa", +"Restore" => "Khôi phục", "Error" => "Lỗi", -"Deleted Files" => "File đã xóa", "restored" => "khôi phục", "Nothing in here. Your trash bin is empty!" => "Không có gì ở đây. Thùng rác của bạn rỗng!", "Name" => "Tên", -"Restore" => "Khôi phục", "Deleted" => "Đã xóa", "Delete" => "Xóa" ); diff --git a/apps/files_trashbin/l10n/zh_CN.php b/apps/files_trashbin/l10n/zh_CN.php index ef6a63b295..49cd412299 100644 --- a/apps/files_trashbin/l10n/zh_CN.php +++ b/apps/files_trashbin/l10n/zh_CN.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "无法彻底删除文件%s", "Couldn't restore %s" => "无法恢复%s", "Deleted files" => "已删除文件", +"Restore" => "恢复", "Error" => "错误", -"Deleted Files" => "已删除文件", "restored" => "已恢复", "Nothing in here. Your trash bin is empty!" => "这里没有东西. 你的回收站是空的!", "Name" => "名称", -"Restore" => "恢复", "Deleted" => "已删除", "Delete" => "删除" ); diff --git a/apps/files_trashbin/l10n/zh_TW.php b/apps/files_trashbin/l10n/zh_TW.php index c42d70790e..014527083e 100644 --- a/apps/files_trashbin/l10n/zh_TW.php +++ b/apps/files_trashbin/l10n/zh_TW.php @@ -3,12 +3,11 @@ $TRANSLATIONS = array( "Couldn't delete %s permanently" => "無法永久刪除 %s", "Couldn't restore %s" => "無法還原 %s", "Deleted files" => "回收桶", +"Restore" => "還原", "Error" => "錯誤", -"Deleted Files" => "已刪除的檔案", "restored" => "已還原", "Nothing in here. Your trash bin is empty!" => "您的回收桶是空的!", "Name" => "名稱", -"Restore" => "還原", "Deleted" => "已刪除", "Delete" => "刪除" ); diff --git a/apps/files_trashbin/lib/helper.php b/apps/files_trashbin/lib/helper.php index e6ca73520a..ebedce31ab 100644 --- a/apps/files_trashbin/lib/helper.php +++ b/apps/files_trashbin/lib/helper.php @@ -8,16 +8,19 @@ class Helper { /** * Retrieves the contents of a trash bin directory. + * * @param string $dir path to the directory inside the trashbin * or empty to retrieve the root of the trashbin + * @param string $sortAttribute attribute to sort on or empty to disable sorting + * @param bool $sortDescending true for descending sort, false otherwise * @return \OCP\Files\FileInfo[] */ - public static function getTrashFiles($dir){ + public static function getTrashFiles($dir, $sortAttribute = '', $sortDescending = false){ $result = array(); $timestamp = null; $user = \OCP\User::getUser(); - $view = new \OC_Filesystemview('/' . $user . '/files_trashbin/files'); + $view = new \OC\Files\View('/' . $user . '/files_trashbin/files'); if (ltrim($dir, '/') !== '' && !$view->is_dir($dir)) { throw new \Exception('Directory does not exists'); @@ -57,8 +60,9 @@ class Helper closedir($dirContent); } - usort($result, array('\OCA\Files\Helper', 'fileCmp')); - + if ($sortAttribute !== '') { + return \OCA\Files\Helper::sortFiles($result, $sortAttribute, $sortDescending); + } return $result; } diff --git a/apps/files_trashbin/lib/hooks.php b/apps/files_trashbin/lib/hooks.php index b2c6bc1df5..b6f0fb7e54 100644 --- a/apps/files_trashbin/lib/hooks.php +++ b/apps/files_trashbin/lib/hooks.php @@ -29,8 +29,8 @@ namespace OCA\Files_Trashbin; class Hooks { /** - * @brief Copy files to trash bin - * @param array + * Copy files to trash bin + * @param array $params * * This function is connected to the delete signal of OC_Filesystem * to copy the file to the trash bin @@ -44,8 +44,8 @@ class Hooks { } /** - * @brief clean up user specific settings if user gets deleted - * @param array with uid + * clean up user specific settings if user gets deleted + * @param array $params array with uid * * This function is connected to the pre_deleteUser signal of OC_Users * to remove the used space for the trash bin stored in the database @@ -56,7 +56,7 @@ class Hooks { Trashbin::deleteUser($uid); } } - + public static function post_write_hook($params) { Trashbin::resizeTrash(\OCP\User::getUser()); } diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 173eb2164c..e95f1b13c3 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -62,7 +62,7 @@ class Trashbin { /** - * @brief copy file to owners trash + * copy file to owners trash * @param string $sourcePath * @param string $owner * @param string $ownerPath @@ -96,7 +96,7 @@ class Trashbin { /** * move file to the trash bin * - * @param $file_path path to the deleted file/directory relative to the files root directory + * @param string $file_path path to the deleted file/directory relative to the files root directory */ public static function move2trash($file_path) { $user = \OCP\User::getUser(); @@ -155,11 +155,11 @@ class Trashbin { /** * Move file versions to trash so that they can be restored later * - * @param $file_path path to original file - * @param $filename of deleted file + * @param string $file_path path to original file + * @param string $filename of deleted file * @param integer $timestamp when the file was deleted * - * @return size of stored versions + * @return int size of stored versions */ private static function retainVersions($file_path, $filename, $timestamp) { $size = 0; @@ -200,11 +200,11 @@ class Trashbin { /** * Move encryption keys to trash so that they can be restored later * - * @param $file_path path to original file - * @param $filename of deleted file + * @param string $file_path path to original file + * @param string $filename of deleted file * @param integer $timestamp when the file was deleted * - * @return size of encryption keys + * @return int size of encryption keys */ private static function retainEncryptionKeys($file_path, $filename, $timestamp) { $size = 0; @@ -216,7 +216,7 @@ class Trashbin { list($owner, $ownerPath) = self::getUidAndFilename($file_path); - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $user); + $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), $user); // disable proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -299,9 +299,9 @@ class Trashbin { /** * restore files from trash bin * - * @param $file path to the deleted file - * @param $filename name of the file - * @param $timestamp time when the file was deleted + * @param string $file path to the deleted file + * @param string $filename name of the file + * @param int $timestamp time when the file was deleted * * @return bool */ @@ -373,14 +373,14 @@ class Trashbin { } /** - * @brief restore versions from trash bin + * restore versions from trash bin * * @param \OC\Files\View $view file view - * @param $file complete path to file - * @param $filename name of file once it was deleted + * @param string $file complete path to file + * @param string $filename name of file once it was deleted * @param string $uniqueFilename new file name to restore the file without overwriting existing files - * @param $location location if file - * @param $timestamp deleteion time + * @param string $location location if file + * @param int $timestamp deleteion time * */ private static function restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp) { @@ -421,14 +421,14 @@ class Trashbin { } /** - * @brief restore encryption keys from trash bin + * restore encryption keys from trash bin * * @param \OC\Files\View $view - * @param $file complete path to file - * @param $filename name of file + * @param string $file complete path to file + * @param string $filename name of file * @param string $uniqueFilename new file name to restore the file without overwriting existing files - * @param $location location of file - * @param $timestamp deleteion time + * @param string $location location of file + * @param int $timestamp deleteion time * */ private static function restoreEncryptionKeys($view, $file, $filename, $uniqueFilename, $location, $timestamp) { @@ -441,7 +441,7 @@ class Trashbin { list($owner, $ownerPath) = self::getUidAndFilename($target); - $util = new \OCA\Encryption\Util(new \OC_FilesystemView('/'), $user); + $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), $user); if ($util->isSystemWideMountPoint($ownerPath)) { $baseDir = '/files_encryption/'; @@ -498,7 +498,7 @@ class Trashbin { $rootView->rename($ownerShareKey, $baseDir . '/share-keys/' . $ownerPath . '.' . $user . '.shareKey'); // try to re-share if file is shared - $filesystemView = new \OC_FilesystemView('/'); + $filesystemView = new \OC\Files\View('/'); $session = new \OCA\Encryption\Session($filesystemView); $util = new \OCA\Encryption\Util($filesystemView, $user); @@ -523,7 +523,7 @@ class Trashbin { } /** - * @brief delete all files from the trash + * delete all files from the trash */ public static function deleteAll() { $user = \OCP\User::getUser(); @@ -537,12 +537,12 @@ class Trashbin { /** - * @brief delete file from trash bin permanently + * delete file from trash bin permanently * - * @param $filename path to the file - * @param $timestamp of deletion time + * @param string $filename path to the file + * @param int $timestamp of deletion time * - * @return size of deleted files + * @return int size of deleted files */ public static function delete($filename, $timestamp = null) { $user = \OCP\User::getUser(); @@ -634,9 +634,9 @@ class Trashbin { /** * check to see whether a file exists in trashbin * - * @param $filename path to the file - * @param $timestamp of deletion time - * @return true if file exists, otherwise false + * @param string $filename path to the file + * @param int $timestamp of deletion time + * @return bool true if file exists, otherwise false */ public static function file_exists($filename, $timestamp = null) { $user = \OCP\User::getUser(); @@ -653,10 +653,10 @@ class Trashbin { } /** - * @brief deletes used space for trash bin in db if user was deleted + * deletes used space for trash bin in db if user was deleted * * @param type $uid id of deleted user - * @return result of db delete operation + * @return bool result of db delete operation */ public static function deleteUser($uid) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?'); @@ -672,7 +672,7 @@ class Trashbin { * calculate remaining free space for trash bin * * @param integer $trashbinSize current size of the trash bin - * @return available free space for trash bin + * @return int available free space for trash bin */ private static function calculateFreeSpace($trashbinSize) { $softQuota = true; @@ -707,7 +707,7 @@ class Trashbin { } /** - * @brief resize trash bin if necessary after a new file was added to ownCloud + * resize trash bin if necessary after a new file was added to ownCloud * @param string $user user id */ public static function resizeTrash($user) { @@ -808,8 +808,8 @@ class Trashbin { /** * find all versions which belong to the file we want to restore * - * @param $filename name of the file which should be restored - * @param $timestamp timestamp when the file was deleted + * @param string $filename name of the file which should be restored + * @param int $timestamp timestamp when the file was deleted */ private static function getVersionsFromTrash($filename, $timestamp) { $view = new \OC\Files\View('/' . \OCP\User::getUser() . '/files_trashbin/versions'); @@ -841,8 +841,8 @@ class Trashbin { /** * find unique extension for restored file if a file with the same name already exists * - * @param $location where the file should be restored - * @param $filename name of the file + * @param string $location where the file should be restored + * @param string $filename name of the file * @param \OC\Files\View $view filesystem view relative to users root directory * @return string with unique extension */ @@ -871,7 +871,7 @@ class Trashbin { } /** - * @brief get the size from a given root folder + * get the size from a given root folder * @param \OC\Files\View $view file view on the root folder * @return integer size of the folder */ @@ -903,7 +903,7 @@ class Trashbin { /** * get current size of trash bin from a given user * - * @param $user user who owns the trash bin + * @param string $user user who owns the trash bin * @return mixed trash bin size or false if no trash bin size is stored */ private static function getTrashbinSize($user) { @@ -925,7 +925,7 @@ class Trashbin { } /** - * @brief check if trash bin is empty for a given user + * check if trash bin is empty for a given user * @param string $user */ public static function isEmpty($user) { diff --git a/apps/files_trashbin/list.php b/apps/files_trashbin/list.php new file mode 100644 index 0000000000..b4047b82ef --- /dev/null +++ b/apps/files_trashbin/list.php @@ -0,0 +1,11 @@ +printPage(); diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index 323e749553..fc18e88c41 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -1,3 +1,4 @@ +
@@ -5,29 +6,27 @@ - - - + - - - - @@ -255,22 +272,6 @@ if (!$_['internetconnectionworking']) { - - - -
+ - t( 'Deleted' )); ?> +
> +
id="publicLinkSettings"> + /> +
/>
- t('Allow users to enable others to upload into their publicly shared folders')); ?> + + /> +
+
> + t( 'Expire after ' )); ?> + ' /> + t( 'days' )); ?> + /> +
+
+ +
+ t('Allow users to share items to the public with links')); ?> + + +
> - /> -
- t( 'Expire after ' )); ?> - ' /> - t( 'days' )); ?> - /> -
- t('Expire shares by default after N days')); ?> -
diff --git a/settings/templates/personal.php b/settings/templates/personal.php index cc1fce88c9..1d1500743a 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -133,21 +133,20 @@ if($_['passwordChangeSupported']) { -
-

t('WebDAV'));?>

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

t( 'Encryption' ) ); ?>

+ + + +
t( "The encryption app is no longer enabled, please decrypt all your files" )); ?>


+
+ + + + + +
> + + t( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." )); ?> +

+ + + + +

+
+ +
+ +
- +

t('Version'));?>

diff --git a/tests/enable_all.php b/tests/enable_all.php index efb43cae50..386ae2070e 100644 --- a/tests/enable_all.php +++ b/tests/enable_all.php @@ -18,7 +18,7 @@ function enableApp($app) { enableApp('files_sharing'); enableApp('files_encryption'); -//enableApp('files_external'); +enableApp('files_external'); enableApp('user_ldap'); enableApp('files_versions'); diff --git a/tests/karma.config.js b/tests/karma.config.js index 338e3f868e..08b49d854e 100644 --- a/tests/karma.config.js +++ b/tests/karma.config.js @@ -43,7 +43,7 @@ module.exports = function(config) { return apps; */ // other apps tests don't run yet... needs further research / clean up - return ['files']; + return ['files', 'files_trashbin']; } // respect NOCOVERAGE env variable diff --git a/tests/lib/app.php b/tests/lib/app.php index 49f40f089b..683820cabb 100644 --- a/tests/lib/app.php +++ b/tests/lib/app.php @@ -1,6 +1,6 @@ + * Copyright (c) 2012 Bernhard Posselt * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. diff --git a/tests/lib/appframework/AppTest.php b/tests/lib/appframework/AppTest.php index 3628e4ceab..92fa483834 100644 --- a/tests/lib/appframework/AppTest.php +++ b/tests/lib/appframework/AppTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/controller/ApiControllerTest.php b/tests/lib/appframework/controller/ApiControllerTest.php new file mode 100644 index 0000000000..b772f540ce --- /dev/null +++ b/tests/lib/appframework/controller/ApiControllerTest.php @@ -0,0 +1,55 @@ +. + * + */ + + +namespace OCP\AppFramework; + +use OC\AppFramework\Http\Request; +use OCP\AppFramework\Http\TemplateResponse; + + +class ChildApiController extends ApiController {}; + + +class ApiControllerTest extends \PHPUnit_Framework_TestCase { + + + public function testCors() { + $request = new Request( + array('server' => array('HTTP_ORIGIN' => 'test')) + ); + $this->controller = new ChildApiController('app', $request, 'verbs', + 'headers', 100); + + $response = $this->controller->preflightedCors(); + + $headers = $response->getHeaders(); + + $this->assertEquals('test', $headers['Access-Control-Allow-Origin']); + $this->assertEquals('verbs', $headers['Access-Control-Allow-Methods']); + $this->assertEquals('headers', $headers['Access-Control-Allow-Headers']); + $this->assertEquals('false', $headers['Access-Control-Allow-Credentials']); + $this->assertEquals(100, $headers['Access-Control-Max-Age']); + } + +} diff --git a/tests/lib/appframework/controller/ControllerTest.php b/tests/lib/appframework/controller/ControllerTest.php index f17d5f24aa..3c1716a91d 100644 --- a/tests/lib/appframework/controller/ControllerTest.php +++ b/tests/lib/appframework/controller/ControllerTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -22,14 +22,35 @@ */ -namespace Test\AppFramework\Controller; +namespace OCP\AppFramework; use OC\AppFramework\Http\Request; -use OCP\AppFramework\Controller; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Http\IResponseSerializer; -class ChildController extends Controller {}; +class ToUpperCaseSerializer implements IResponseSerializer { + public function serialize($response) { + return array(strtoupper($response)); + } +} + +class ChildController extends Controller { + public function custom($in) { + $this->registerResponder('json', function ($response) { + return new JSONResponse(array(strlen($response))); + }); + + return $in; + } + + public function serializer($in) { + $this->registerSerializer(new ToUpperCaseSerializer()); + + return $in; + } +}; class ControllerTest extends \PHPUnit_Framework_TestCase { @@ -129,4 +150,36 @@ class ControllerTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('daheim', $this->controller->env('PATH')); } + + /** + * @expectedException \DomainException + */ + public function testFormatResonseInvalidFormat() { + $this->controller->buildResponse(null, 'test'); + } + + + public function testFormat() { + $response = $this->controller->buildResponse(array('hi'), 'json'); + + $this->assertEquals(array('hi'), $response->getData()); + } + + + public function testCustomFormatter() { + $response = $this->controller->custom('hi'); + $response = $this->controller->buildResponse($response, 'json'); + + $this->assertEquals(array(2), $response->getData()); + } + + + public function testCustomSerializer() { + $response = $this->controller->serializer('hi'); + $response = $this->controller->buildResponse($response, 'json'); + + $this->assertEquals(array('HI'), $response->getData()); + } + + } diff --git a/tests/lib/appframework/db/EntityTest.php b/tests/lib/appframework/db/EntityTest.php new file mode 100644 index 0000000000..9de44b9b3b --- /dev/null +++ b/tests/lib/appframework/db/EntityTest.php @@ -0,0 +1,223 @@ +. +* +*/ + +namespace OCP\AppFramework\Db; + + +/** + * @method integer getId() + * @method void setId(integer $id) + * @method integer getTestId() + * @method void setTestId(integer $id) + * @method string getName() + * @method void setName(string $name) + * @method string getEmail() + * @method void setEmail(string $email) + * @method string getPreName() + * @method void setPreName(string $preName) + */ +class TestEntity extends Entity { + public $name; + public $email; + public $testId; + public $preName; + + public function __construct($name=null){ + $this->addType('testId', 'integer'); + $this->name = $name; + } +}; + + +class EntityTest extends \PHPUnit_Framework_TestCase { + + private $entity; + + protected function setUp(){ + $this->entity = new TestEntity(); + } + + + public function testResetUpdatedFields(){ + $entity = new TestEntity(); + $entity->setId(3); + $entity->resetUpdatedFields(); + + $this->assertEquals(array(), $entity->getUpdatedFields()); + } + + + public function testFromRow(){ + $row = array( + 'pre_name' => 'john', + 'email' => 'john@something.com' + ); + $this->entity = TestEntity::fromRow($row); + + $this->assertEquals($row['pre_name'], $this->entity->getPreName()); + $this->assertEquals($row['email'], $this->entity->getEmail()); + } + + + public function testGetSetId(){ + $id = 3; + $this->entity->setId(3); + + $this->assertEquals($id, $this->entity->getId()); + } + + + public function testColumnToPropertyNoReplacement(){ + $column = 'my'; + $this->assertEquals('my', + $this->entity->columnToProperty($column)); + } + + + public function testColumnToProperty(){ + $column = 'my_attribute'; + $this->assertEquals('myAttribute', + $this->entity->columnToProperty($column)); + } + + + public function testPropertyToColumnNoReplacement(){ + $property = 'my'; + $this->assertEquals('my', + $this->entity->propertyToColumn($property)); + } + + + public function testSetterMarksFieldUpdated(){ + $this->entity->setId(3); + + $this->assertContains('id', $this->entity->getUpdatedFields()); + } + + + public function testCallShouldOnlyWorkForGetterSetter(){ + $this->setExpectedException('\BadFunctionCallException'); + + $this->entity->something(); + } + + + public function testGetterShouldFailIfAttributeNotDefined(){ + $this->setExpectedException('\BadFunctionCallException'); + + $this->entity->getTest(); + } + + + public function testSetterShouldFailIfAttributeNotDefined(){ + $this->setExpectedException('\BadFunctionCallException'); + + $this->entity->setTest(); + } + + + public function testFromRowShouldNotAssignEmptyArray(){ + $row = array(); + $entity2 = new TestEntity(); + + $this->entity = TestEntity::fromRow($row); + $this->assertEquals($entity2, $this->entity); + } + + + public function testIdGetsConvertedToInt(){ + $row = array('id' => '4'); + + $this->entity = TestEntity::fromRow($row); + $this->assertSame(4, $this->entity->getId()); + } + + + public function testSetType(){ + $row = array('testId' => '4'); + + $this->entity = TestEntity::fromRow($row); + $this->assertSame(4, $this->entity->getTestId()); + } + + + public function testFromParams(){ + $params = array( + 'testId' => 4, + 'email' => 'john@doe' + ); + + $entity = TestEntity::fromParams($params); + + $this->assertEquals($params['testId'], $entity->getTestId()); + $this->assertEquals($params['email'], $entity->getEmail()); + $this->assertTrue($entity instanceof TestEntity); + } + + public function testSlugify(){ + $entity = new TestEntity(); + $entity->setName('Slugify this!'); + $this->assertEquals('slugify-this', $entity->slugify('name')); + $entity->setName('°!"§$%&/()=?`´ß\}][{³²#\'+~*-_.:,;<>|äöüÄÖÜSlugify this!'); + $this->assertEquals('slugify-this', $entity->slugify('name')); + } + + + public function testSetterCasts() { + $entity = new TestEntity(); + $entity->setId('3'); + $this->assertSame(3, $entity->getId()); + } + + + public function testSetterDoesNotCastOnNull() { + $entity = new TestEntity(); + $entity->setId(null); + $this->assertSame(null, $entity->getId()); + } + + + public function testGetFieldTypes() { + $entity = new TestEntity(); + $this->assertEquals(array( + 'id' => 'integer', + 'testId' => 'integer' + ), $entity->getFieldTypes()); + } + + + public function testGetItInt() { + $entity = new TestEntity(); + $entity->setId(3); + $this->assertEquals('integer', gettype($entity->getId())); + } + + + public function testFieldsNotMarkedUpdatedIfNothingChanges() { + $entity = new TestEntity('hey'); + $entity->setName('hey'); + $this->assertEquals(0, count($entity->getUpdatedFields())); + } + + +} \ No newline at end of file diff --git a/tests/lib/appframework/db/MapperTest.php b/tests/lib/appframework/db/MapperTest.php new file mode 100644 index 0000000000..4ddc4ef042 --- /dev/null +++ b/tests/lib/appframework/db/MapperTest.php @@ -0,0 +1,279 @@ +. + * + */ + + +namespace OCP\AppFramework\Db; + +use \OCP\IDb; + + +require_once __DIR__ . '/MapperTestUtility.php'; + +/** + * @method integer getId() + * @method void setId(integer $id) + * @method string getEmail() + * @method void setEmail(string $email) + * @method string getPreName() + * @method void setPreName(string $preName) + */ +class Example extends Entity { + public $preName; + public $email; +}; + + +class ExampleMapper extends Mapper { + public function __construct(IDb $db){ parent::__construct($db, 'table'); } + public function find($table, $id){ return $this->findOneQuery($table, $id); } + public function findOneEntity($table, $id){ return $this->findEntity($table, $id); } + public function findAllEntities($table){ return $this->findEntities($table); } + public function mapRow($row){ return $this->mapRowToEntity($row); } +} + + +class MapperTest extends MapperTestUtility { + + private $mapper; + + public function setUp(){ + parent::setUp(); + $this->mapper = new ExampleMapper($this->db); + } + + + public function testMapperShouldSetTableName(){ + $this->assertEquals('*PREFIX*table', $this->mapper->getTableName()); + } + + + public function testFindQuery(){ + $sql = 'hi'; + $params = array('jo'); + $rows = array( + array('hi') + ); + $this->setMapperResult($sql, $params, $rows); + $this->mapper->find($sql, $params); + } + + public function testFindEntity(){ + $sql = 'hi'; + $params = array('jo'); + $rows = array( + array('pre_name' => 'hi') + ); + $this->setMapperResult($sql, $params, $rows); + $this->mapper->findOneEntity($sql, $params); + } + + public function testFindNotFound(){ + $sql = 'hi'; + $params = array('jo'); + $rows = array(); + $this->setMapperResult($sql, $params, $rows); + $this->setExpectedException( + '\OCP\AppFramework\Db\DoesNotExistException'); + $this->mapper->find($sql, $params); + } + + public function testFindEntityNotFound(){ + $sql = 'hi'; + $params = array('jo'); + $rows = array(); + $this->setMapperResult($sql, $params, $rows); + $this->setExpectedException( + '\OCP\AppFramework\Db\DoesNotExistException'); + $this->mapper->findOneEntity($sql, $params); + } + + public function testFindMultiple(){ + $sql = 'hi'; + $params = array('jo'); + $rows = array( + array('jo'), array('ho') + ); + $this->setMapperResult($sql, $params, $rows); + $this->setExpectedException( + '\OCP\AppFramework\Db\MultipleObjectsReturnedException'); + $this->mapper->find($sql, $params); + } + + public function testFindEntityMultiple(){ + $sql = 'hi'; + $params = array('jo'); + $rows = array( + array('jo'), array('ho') + ); + $this->setMapperResult($sql, $params, $rows); + $this->setExpectedException( + '\OCP\AppFramework\Db\MultipleObjectsReturnedException'); + $this->mapper->findOneEntity($sql, $params); + } + + + public function testDelete(){ + $sql = 'DELETE FROM `*PREFIX*table` WHERE `id` = ?'; + $params = array(2); + + $this->setMapperResult($sql, $params); + $entity = new Example(); + $entity->setId($params[0]); + + $this->mapper->delete($entity); + } + + + public function testCreate(){ + $this->db->expects($this->once()) + ->method('getInsertId') + ->with($this->equalTo('*PREFIX*table')) + ->will($this->returnValue(3)); + $this->mapper = new ExampleMapper($this->db); + + $sql = 'INSERT INTO `*PREFIX*table`(`pre_name`,`email`) ' . + 'VALUES(?,?)'; + $params = array('john', 'my@email'); + $entity = new Example(); + $entity->setPreName($params[0]); + $entity->setEmail($params[1]); + + $this->setMapperResult($sql, $params); + + $this->mapper->insert($entity); + } + + + public function testCreateShouldReturnItemWithCorrectInsertId(){ + $this->db->expects($this->once()) + ->method('getInsertId') + ->with($this->equalTo('*PREFIX*table')) + ->will($this->returnValue(3)); + $this->mapper = new ExampleMapper($this->db); + + $sql = 'INSERT INTO `*PREFIX*table`(`pre_name`,`email`) ' . + 'VALUES(?,?)'; + $params = array('john', 'my@email'); + $entity = new Example(); + $entity->setPreName($params[0]); + $entity->setEmail($params[1]); + + $this->setMapperResult($sql, $params); + + $result = $this->mapper->insert($entity); + + $this->assertEquals(3, $result->getId()); + } + + + public function testUpdate(){ + $sql = 'UPDATE `*PREFIX*table` ' . + 'SET ' . + '`pre_name` = ?,'. + '`email` = ? ' . + 'WHERE `id` = ?'; + + $params = array('john', 'my@email', 1); + $entity = new Example(); + $entity->setPreName($params[0]); + $entity->setEmail($params[1]); + $entity->setId($params[2]); + + $this->setMapperResult($sql, $params); + + $this->mapper->update($entity); + } + + + public function testUpdateNoId(){ + $params = array('john', 'my@email'); + $entity = new Example(); + $entity->setPreName($params[0]); + $entity->setEmail($params[1]); + + $this->setExpectedException('InvalidArgumentException'); + + $this->mapper->update($entity); + } + + + public function testUpdateNothingChangedNoQuery(){ + $params = array('john', 'my@email'); + $entity = new Example(); + $entity->setId(3); + $entity->setEmail($params[1]); + $entity->resetUpdatedFields(); + + $this->db->expects($this->never()) + ->method('prepareQuery'); + + $this->mapper->update($entity); + } + + + public function testMapRowToEntity(){ + $entity1 = $this->mapper->mapRow(array('pre_name' => 'test1', 'email' => 'test2')); + $entity2 = new Example(); + $entity2->setPreName('test1'); + $entity2->setEmail('test2'); + $entity2->resetUpdatedFields(); + $this->assertEquals($entity2, $entity1); + } + + public function testFindEntities(){ + $sql = 'hi'; + $rows = array( + array('pre_name' => 'hi') + ); + $entity = new Example(); + $entity->setPreName('hi'); + $entity->resetUpdatedFields(); + $this->setMapperResult($sql, array(), $rows); + $result = $this->mapper->findAllEntities($sql); + $this->assertEquals(array($entity), $result); + } + + public function testFindEntitiesNotFound(){ + $sql = 'hi'; + $rows = array(); + $this->setMapperResult($sql, array(), $rows); + $result = $this->mapper->findAllEntities($sql); + $this->assertEquals(array(), $result); + } + + public function testFindEntitiesMultiple(){ + $sql = 'hi'; + $rows = array( + array('pre_name' => 'jo'), array('email' => 'ho') + ); + $entity1 = new Example(); + $entity1->setPreName('jo'); + $entity1->resetUpdatedFields(); + $entity2 = new Example(); + $entity2->setEmail('ho'); + $entity2->resetUpdatedFields(); + $this->setMapperResult($sql, array(), $rows); + $result = $this->mapper->findAllEntities($sql); + $this->assertEquals(array($entity1, $entity2), $result); + } +} \ No newline at end of file diff --git a/tests/lib/appframework/db/MapperTestUtility.php b/tests/lib/appframework/db/MapperTestUtility.php new file mode 100644 index 0000000000..fc0e5c2c44 --- /dev/null +++ b/tests/lib/appframework/db/MapperTestUtility.php @@ -0,0 +1,179 @@ +. + * + */ + + +namespace OCP\AppFramework\Db; + + +/** + * Simple utility class for testing mappers + */ +abstract class MapperTestUtility extends \PHPUnit_Framework_TestCase { + + + protected $db; + private $query; + private $pdoResult; + private $queryAt; + private $prepareAt; + private $fetchAt; + private $iterators; + + + /** + * Run this function before the actual test to either set or initialize the + * db. After this the db can be accessed by using $this->db + */ + protected function setUp(){ + $this->db = $this->getMockBuilder( + '\OCP\IDb') + ->disableOriginalConstructor() + ->getMock(); + + $this->query = $this->getMock('Query', array('execute', 'bindValue')); + $this->pdoResult = $this->getMock('Result', array('fetch')); + $this->queryAt = 0; + $this->prepareAt = 0; + $this->iterators = array(); + $this->fetchAt = 0; + } + + + /** + * Create mocks and set expected results for database queries + * @param string $sql the sql query that you expect to receive + * @param array $arguments the expected arguments for the prepare query + * method + * @param array $returnRows the rows that should be returned for the result + * of the database query. If not provided, it wont be assumed that fetch + * will be called on the result + */ + protected function setMapperResult($sql, $arguments=array(), $returnRows=array(), + $limit=null, $offset=null){ + + $this->iterators[] = new ArgumentIterator($returnRows); + + $iterators = $this->iterators; + $fetchAt = $this->fetchAt; + + $this->pdoResult->expects($this->any()) + ->method('fetch') + ->will($this->returnCallback( + function() use ($iterators, $fetchAt){ + $iterator = $iterators[$fetchAt]; + $result = $iterator->next(); + + if($result === false) { + $fetchAt++; + } + + return $result; + } + )); + + $index = 1; + foreach($arguments as $argument) { + switch (gettype($argument)) { + case 'integer': + $pdoConstant = \PDO::PARAM_INT; + break; + + case 'NULL': + $pdoConstant = \PDO::PARAM_NULL; + break; + + case 'boolean': + $pdoConstant = \PDO::PARAM_BOOL; + break; + + default: + $pdoConstant = \PDO::PARAM_STR; + break; + } + $this->query->expects($this->at($this->queryAt)) + ->method('bindValue') + ->with($this->equalTo($index), + $this->equalTo($argument), + $this->equalTo($pdoConstant)); + $index++; + $this->queryAt++; + } + + $this->query->expects($this->at($this->queryAt)) + ->method('execute') + ->with() + ->will($this->returnValue($this->pdoResult)); + $this->queryAt++; + + if($limit === null && $offset === null) { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepareQuery') + ->with($this->equalTo($sql)) + ->will(($this->returnValue($this->query))); + } elseif($limit !== null && $offset === null) { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepareQuery') + ->with($this->equalTo($sql), $this->equalTo($limit)) + ->will(($this->returnValue($this->query))); + } elseif($limit === null && $offset !== null) { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepareQuery') + ->with($this->equalTo($sql), + $this->equalTo(null), + $this->equalTo($offset)) + ->will(($this->returnValue($this->query))); + } else { + $this->db->expects($this->at($this->prepareAt)) + ->method('prepareQuery') + ->with($this->equalTo($sql), + $this->equalTo($limit), + $this->equalTo($offset)) + ->will(($this->returnValue($this->query))); + } + $this->prepareAt++; + $this->fetchAt++; + + } + + +} + + +class ArgumentIterator { + + private $arguments; + + public function __construct($arguments){ + $this->arguments = $arguments; + } + + public function next(){ + $result = array_shift($this->arguments); + if($result === null){ + return false; + } else { + return $result; + } + } +} + diff --git a/tests/lib/appframework/dependencyinjection/DIContainerTest.php b/tests/lib/appframework/dependencyinjection/DIContainerTest.php index d1bc900fb2..acc5c2e66d 100644 --- a/tests/lib/appframework/dependencyinjection/DIContainerTest.php +++ b/tests/lib/appframework/dependencyinjection/DIContainerTest.php @@ -5,8 +5,8 @@ * * @author Bernhard Posselt * @author Morris Jobke - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com - * @copyright 2013 Morris Jobke morris.jobke@gmail.com + * @copyright 2012 Bernhard Posselt + * @copyright 2013 Morris Jobke * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/http/DispatcherTest.php b/tests/lib/appframework/http/DispatcherTest.php index 9841dcaa1f..8117eec207 100644 --- a/tests/lib/appframework/http/DispatcherTest.php +++ b/tests/lib/appframework/http/DispatcherTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -25,8 +25,28 @@ namespace OC\AppFramework\Http; use OC\AppFramework\Middleware\MiddlewareDispatcher; +use OC\AppFramework\Utility\ControllerMethodReflector; use OCP\AppFramework\Http; -//require_once(__DIR__ . "/../classloader.php"); +use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\Controller; + + +class TestController extends Controller { + public function __construct($appName, $request) { + parent::__construct($appName, $request); + } + + /** + * @param int $int + * @param bool $bool + */ + public function exec($int, $bool, $test=4, $test2=1) { + $this->registerResponder('text', function($in) { + return new JSONResponse(array('text' => $in)); + }); + return array($int, $bool, $test, $test2); + } +} class DispatcherTest extends \PHPUnit_Framework_TestCase { @@ -39,6 +59,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { private $lastModified; private $etag; private $http; + private $reflector; protected function setUp() { $this->controllerMethod = 'test'; @@ -64,8 +85,17 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { '\OCP\AppFramework\Controller', array($this->controllerMethod), array($app, $request)); + $this->request = $this->getMockBuilder( + '\OC\AppFramework\Http\Request') + ->disableOriginalConstructor() + ->getMock(); + + $this->reflector = new ControllerMethodReflector(); + $this->dispatcher = new Dispatcher( - $this->http, $this->middlewareDispatcher); + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); $this->response = $this->getMockBuilder( '\OCP\AppFramework\Http\Response') @@ -81,7 +111,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { * @param string $out * @param string $httpHeaders */ - private function setMiddlewareExpections($out=null, + private function setMiddlewareExpectations($out=null, $httpHeaders=null, $responseHeaders=array(), $ex=false, $catchEx=true) { @@ -159,14 +189,12 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { ->with($this->equalTo($this->controller), $this->equalTo($this->controllerMethod), $this->equalTo($out)) - ->will($this->returnValue($out)); - - + ->will($this->returnValue($out)); } public function testDispatcherReturnsArrayWith2Entries() { - $this->setMiddlewareExpections(); + $this->setMiddlewareExpectations(); $response = $this->dispatcher->dispatch($this->controller, $this->controllerMethod); @@ -180,7 +208,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { $out = 'yo'; $httpHeaders = 'Http'; $responseHeaders = array('hell' => 'yeah'); - $this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders); + $this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders); $response = $this->dispatcher->dispatch($this->controller, $this->controllerMethod); @@ -195,7 +223,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { $out = 'yo'; $httpHeaders = 'Http'; $responseHeaders = array('hell' => 'yeah'); - $this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders, true); + $this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true); $response = $this->dispatcher->dispatch($this->controller, $this->controllerMethod); @@ -210,7 +238,7 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { $out = 'yo'; $httpHeaders = 'Http'; $responseHeaders = array('hell' => 'yeah'); - $this->setMiddlewareExpections($out, $httpHeaders, $responseHeaders, true, false); + $this->setMiddlewareExpectations($out, $httpHeaders, $responseHeaders, true, false); $this->setExpectedException('\Exception'); $response = $this->dispatcher->dispatch($this->controller, @@ -218,4 +246,148 @@ class DispatcherTest extends \PHPUnit_Framework_TestCase { } + + private function dispatcherPassthrough() { + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeController'); + $this->middlewareDispatcher->expects($this->once()) + ->method('afterController') + ->will($this->returnCallback(function($a, $b, $in) { + return $in; + })); + $this->middlewareDispatcher->expects($this->once()) + ->method('beforeOutput') + ->will($this->returnCallback(function($a, $b, $in) { + return $in; + })); + } + + + public function testControllerParametersInjected() { + $this->request = new Request(array( + 'post' => array( + 'int' => '3', + 'bool' => 'false' + ), + 'method' => 'POST' + )); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('[3,true,4,1]', $response[2]); + } + + + public function testControllerParametersInjectedDefaultOverwritten() { + $this->request = new Request(array( + 'post' => array( + 'int' => '3', + 'bool' => 'false', + 'test2' => 7 + ), + 'method' => 'POST' + )); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('[3,true,4,7]', $response[2]); + } + + + + public function testResponseTransformedByUrlFormat() { + $this->request = new Request(array( + 'post' => array( + 'int' => '3', + 'bool' => 'false' + ), + 'urlParams' => array( + 'format' => 'text' + ), + 'method' => 'GET' + )); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('{"text":[3,false,4,1]}', $response[2]); + } + + + public function testResponseTransformedByAcceptHeader() { + $this->request = new Request(array( + 'post' => array( + 'int' => '3', + 'bool' => 'false' + ), + 'server' => array( + 'HTTP_ACCEPT' => 'application/text, test', + 'HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded' + ), + 'method' => 'PUT' + )); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('{"text":[3,false,4,1]}', $response[2]); + } + + + public function testResponsePrimarilyTransformedByParameterFormat() { + $this->request = new Request(array( + 'post' => array( + 'int' => '3', + 'bool' => 'false' + ), + 'get' => array( + 'format' => 'text' + ), + 'server' => array( + 'HTTP_ACCEPT' => 'application/json, test' + ), + 'method' => 'POST' + )); + $this->dispatcher = new Dispatcher( + $this->http, $this->middlewareDispatcher, $this->reflector, + $this->request + ); + $controller = new TestController('app', $this->request); + + // reflector is supposed to be called once + $this->dispatcherPassthrough(); + $response = $this->dispatcher->dispatch($controller, 'exec'); + + $this->assertEquals('{"text":[3,true,4,1]}', $response[2]); + } + + + + } diff --git a/tests/lib/appframework/http/DownloadResponseTest.php b/tests/lib/appframework/http/DownloadResponseTest.php index b305c63ad4..5be16ce3c4 100644 --- a/tests/lib/appframework/http/DownloadResponseTest.php +++ b/tests/lib/appframework/http/DownloadResponseTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/http/HttpTest.php b/tests/lib/appframework/http/HttpTest.php index 0bdcee24c9..c62fa43863 100644 --- a/tests/lib/appframework/http/HttpTest.php +++ b/tests/lib/appframework/http/HttpTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/http/JSONResponseTest.php b/tests/lib/appframework/http/JSONResponseTest.php index fbaae1b922..c0c58ebf76 100644 --- a/tests/lib/appframework/http/JSONResponseTest.php +++ b/tests/lib/appframework/http/JSONResponseTest.php @@ -5,8 +5,8 @@ * * @author Bernhard Posselt * @author Morris Jobke - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com - * @copyright 2013 Morris Jobke morris.jobke@gmail.com + * @copyright 2012 Bernhard Posselt + * @copyright 2013 Morris Jobke * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/http/RedirectResponseTest.php b/tests/lib/appframework/http/RedirectResponseTest.php index f62b420f4e..dfd0d7ee7d 100644 --- a/tests/lib/appframework/http/RedirectResponseTest.php +++ b/tests/lib/appframework/http/RedirectResponseTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/http/ResponseTest.php b/tests/lib/appframework/http/ResponseTest.php index 27350725d7..e83fe9e2d8 100644 --- a/tests/lib/appframework/http/ResponseTest.php +++ b/tests/lib/appframework/http/ResponseTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -42,7 +42,7 @@ class ResponseTest extends \PHPUnit_Framework_TestCase { public function testAddHeader(){ - $this->childResponse->addHeader('hello', 'world'); + $this->childResponse->addHeader(' hello ', 'world'); $headers = $this->childResponse->getHeaders(); $this->assertEquals('world', $headers['hello']); } diff --git a/tests/lib/appframework/http/TemplateResponseTest.php b/tests/lib/appframework/http/TemplateResponseTest.php index 0b158edff6..afdcf322b8 100644 --- a/tests/lib/appframework/http/TemplateResponseTest.php +++ b/tests/lib/appframework/http/TemplateResponseTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -51,6 +51,22 @@ class TemplateResponseTest extends \PHPUnit_Framework_TestCase { } + public function testSetParamsConstructor(){ + $params = array('hi' => 'yo'); + $this->tpl = new TemplateResponse($this->api, 'home', $params); + + $this->assertEquals(array('hi' => 'yo'), $this->tpl->getParams()); + } + + + public function testSetRenderAsConstructor(){ + $renderAs = 'myrender'; + $this->tpl = new TemplateResponse($this->api, 'home', array(), $renderAs); + + $this->assertEquals($renderAs, $this->tpl->getRenderAs()); + } + + public function testSetParams(){ $params = array('hi' => 'yo'); $this->tpl->setParams($params); @@ -63,36 +79,6 @@ class TemplateResponseTest extends \PHPUnit_Framework_TestCase { $this->assertEquals('home', $this->tpl->getTemplateName()); } - -// public function testRender(){ -// $ocTpl = $this->getMock('Template', array('fetchPage')); -// $ocTpl->expects($this->once()) -// ->method('fetchPage'); -// -// $tpl = new TemplateResponse('core', 'error'); -// -// $tpl->render(); -// } -// -// -// public function testRenderAssignsParams(){ -// $params = array('john' => 'doe'); -// -// $tpl = new TemplateResponse('app', 'home'); -// $tpl->setParams($params); -// -// $tpl->render(); -// } -// -// -// public function testRenderDifferentApp(){ -// -// $tpl = new TemplateResponse('app', 'home', 'app2'); -// -// $tpl->render(); -// } - - public function testGetRenderAs(){ $render = 'myrender'; $this->tpl->renderAs($render); diff --git a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php index 935f97d2a6..b1a58e2128 100644 --- a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php +++ b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/middleware/MiddlewareTest.php b/tests/lib/appframework/middleware/MiddlewareTest.php index 7a93c0d4dd..814efdd811 100644 --- a/tests/lib/appframework/middleware/MiddlewareTest.php +++ b/tests/lib/appframework/middleware/MiddlewareTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php new file mode 100644 index 0000000000..79cd3b278a --- /dev/null +++ b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php @@ -0,0 +1,87 @@ + + * @copyright Bernhard Posselt 2014 + */ + + +namespace OC\AppFramework\Middleware\Security; + +use OC\AppFramework\Http\Request; +use OC\AppFramework\Utility\ControllerMethodReflector; + +use OCP\AppFramework\Http\Response; + + +class CORSMiddlewareTest extends \PHPUnit_Framework_TestCase { + + private $reflector; + + protected function setUp() { + $this->reflector = new ControllerMethodReflector(); + } + + /** + * @CORS + */ + public function testSetCORSAPIHeader() { + $request = new Request( + array('server' => array('HTTP_ORIGIN' => 'test')) + ); + $this->reflector->reflect($this, __FUNCTION__); + $middleware = new CORSMiddleware($request, $this->reflector); + + $response = $middleware->afterController($this, __FUNCTION__, new Response()); + $headers = $response->getHeaders(); + $this->assertEquals('test', $headers['Access-Control-Allow-Origin']); + } + + + public function testNoAnnotationNoCORSHEADER() { + $request = new Request( + array('server' => array('HTTP_ORIGIN' => 'test')) + ); + $middleware = new CORSMiddleware($request, $this->reflector); + + $response = $middleware->afterController($this, __FUNCTION__, new Response()); + $headers = $response->getHeaders(); + $this->assertFalse(array_key_exists('Access-Control-Allow-Origin', $headers)); + } + + + /** + * @CORS + */ + public function testNoOriginHeaderNoCORSHEADER() { + $request = new Request(); + $this->reflector->reflect($this, __FUNCTION__); + $middleware = new CORSMiddleware($request, $this->reflector); + + $response = $middleware->afterController($this, __FUNCTION__, new Response()); + $headers = $response->getHeaders(); + $this->assertFalse(array_key_exists('Access-Control-Allow-Origin', $headers)); + } + + + /** + * @CORS + * @expectedException \OC\AppFramework\Middleware\Security\SecurityException + */ + public function testCorsIgnoredIfWithCredentialsHeaderPresent() { + $request = new Request( + array('server' => array('HTTP_ORIGIN' => 'test')) + ); + $this->reflector->reflect($this, __FUNCTION__); + $middleware = new CORSMiddleware($request, $this->reflector); + + $response = new Response(); + $response->addHeader('AcCess-control-Allow-Credentials ', 'TRUE'); + $response = $middleware->afterController($this, __FUNCTION__, $response); + } + +} diff --git a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php index 19e8a68c38..6a1bbf72c1 100644 --- a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php +++ b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php @@ -4,7 +4,7 @@ * ownCloud - App Framework * * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -26,6 +26,7 @@ namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Http; use OC\AppFramework\Http\Request; +use OC\AppFramework\Utility\ControllerMethodReflector; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\JSONResponse; @@ -37,14 +38,16 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { private $secException; private $secAjaxException; private $request; + private $reader; public function setUp() { $api = $this->getMock('OC\AppFramework\DependencyInjection\DIContainer', array(), array('test')); $this->controller = $this->getMock('OCP\AppFramework\Controller', array(), array($api, new Request())); + $this->reader = new ControllerMethodReflector(); $this->request = new Request(); - $this->middleware = new SecurityMiddleware($api, $this->request); + $this->middleware = new SecurityMiddleware($api, $this->request, $this->reader); $this->secException = new SecurityException('hey', false); $this->secAjaxException = new SecurityException('hey', true); } @@ -68,7 +71,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { $api->expects($this->any())->method('getServer') ->will($this->returnValue($serverMock)); - $sec = new SecurityMiddleware($api, $this->request); + $sec = new SecurityMiddleware($api, $this->request, $this->reader); + $this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); } @@ -99,11 +103,12 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->will($this->returnValue(true)); } - $sec = new SecurityMiddleware($api, $this->request); + $sec = new SecurityMiddleware($api, $this->request, $this->reader); try { - $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', - $method); + $controller = '\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest'; + $this->reader->reflect($controller, $method); + $sec->beforeController($controller, $method); } catch (SecurityException $ex){ $this->assertEquals($status, $ex->getCode()); } @@ -184,7 +189,9 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->method('isLoggedIn') ->will($this->returnValue(true)); - $sec = new SecurityMiddleware($api, $this->request); + $sec = new SecurityMiddleware($api, $this->request, $this->reader); + $this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', + 'testNoChecks'); $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testNoChecks'); } @@ -207,7 +214,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->will($this->returnValue(true)); } - $sec = new SecurityMiddleware($api, $this->request); + $sec = new SecurityMiddleware($api, $this->request, $this->reader); if($shouldFail){ $this->setExpectedException('\OC\AppFramework\Middleware\Security\SecurityException'); @@ -215,6 +222,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { $this->setExpectedException(null); } + $this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', $method); } @@ -230,7 +238,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->method('passesCSRFCheck') ->will($this->returnValue(false)); - $sec = new SecurityMiddleware($api, $request); + $sec = new SecurityMiddleware($api, $request, $this->reader); + $this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testCsrfCheck'); $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testCsrfCheck'); } @@ -246,7 +255,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->method('passesCSRFCheck') ->will($this->returnValue(false)); - $sec = new SecurityMiddleware($api, $request); + $sec = new SecurityMiddleware($api, $request, $this->reader); + $this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testNoCsrfCheck'); $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testNoCsrfCheck'); } @@ -261,7 +271,8 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { ->method('passesCSRFCheck') ->will($this->returnValue(true)); - $sec = new SecurityMiddleware($api, $request); + $sec = new SecurityMiddleware($api, $request, $this->reader); + $this->reader->reflect('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testFailCsrfCheck'); $sec->beforeController('\OC\AppFramework\Middleware\Security\SecurityMiddlewareTest', 'testFailCsrfCheck'); } @@ -318,7 +329,7 @@ class SecurityMiddlewareTest extends \PHPUnit_Framework_TestCase { $this->request = new Request( array('server' => array('HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'))); - $this->middleware = new SecurityMiddleware($api, $this->request); + $this->middleware = new SecurityMiddleware($api, $this->request, $this->reader); $response = $this->middleware->afterException($this->controller, 'test', $this->secException); diff --git a/tests/lib/appframework/utility/ControllerMethodReflectorTest.php b/tests/lib/appframework/utility/ControllerMethodReflectorTest.php new file mode 100644 index 0000000000..8939a203ed --- /dev/null +++ b/tests/lib/appframework/utility/ControllerMethodReflectorTest.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 OC\AppFramework\Utility; + + +class ControllerMethodReflectorTest extends \PHPUnit_Framework_TestCase { + + + /** + * @Annotation + */ + public function testReadAnnotation(){ + $reader = new ControllerMethodReflector(); + $reader->reflect( + '\OC\AppFramework\Utility\ControllerMethodReflectorTest', + 'testReadAnnotation' + ); + + $this->assertTrue($reader->hasAnnotation('Annotation')); + } + + + /** + * @Annotation + * @param test + */ + public function testReadAnnotationNoLowercase(){ + $reader = new ControllerMethodReflector(); + $reader->reflect( + '\OC\AppFramework\Utility\ControllerMethodReflectorTest', + 'testReadAnnotationNoLowercase' + ); + + $this->assertTrue($reader->hasAnnotation('Annotation')); + $this->assertFalse($reader->hasAnnotation('param')); + } + + + /** + * @Annotation + * @param int $test + */ + public function testReadTypeIntAnnotations(){ + $reader = new ControllerMethodReflector(); + $reader->reflect( + '\OC\AppFramework\Utility\ControllerMethodReflectorTest', + 'testReadTypeIntAnnotations' + ); + + $this->assertEquals('int', $reader->getType('test')); + } + + + /** + * @Annotation + * @param double $test something special + */ + public function testReadTypeDoubleAnnotations(){ + $reader = new ControllerMethodReflector(); + $reader->reflect( + '\OC\AppFramework\Utility\ControllerMethodReflectorTest', + 'testReadTypeDoubleAnnotations' + ); + + $this->assertEquals('double', $reader->getType('test')); + } + + + public function arguments($arg, $arg2='hi') {} + public function testReflectParameters() { + $reader = new ControllerMethodReflector(); + $reader->reflect( + '\OC\AppFramework\Utility\ControllerMethodReflectorTest', + 'arguments' + ); + + $this->assertEquals(array('arg' => null, 'arg2' => 'hi'), $reader->getParameters()); + } + + + public function arguments2($arg) {} + public function testReflectParameters2() { + $reader = new ControllerMethodReflector(); + $reader->reflect( + '\OC\AppFramework\Utility\ControllerMethodReflectorTest', + 'arguments2' + ); + + $this->assertEquals(array('arg' => null), $reader->getParameters()); + } + + +} diff --git a/tests/lib/errorHandler.php b/tests/lib/errorHandler.php index 32396eafbe..58db80b3c6 100644 --- a/tests/lib/errorHandler.php +++ b/tests/lib/errorHandler.php @@ -23,7 +23,7 @@ class Test_ErrorHandler extends \PHPUnit_Framework_TestCase { /** - * @brief provide username, password combinations for testRemovePassword + * provide username, password combinations for testRemovePassword * @return array */ function passwordProvider() { @@ -53,7 +53,7 @@ class Test_ErrorHandler extends \PHPUnit_Framework_TestCase { } /** - * @brief dummy class to access protected methods of \OC\Log\ErrorHandler + * dummy class to access protected methods of \OC\Log\ErrorHandler */ class TestableErrorHandler extends \OC\Log\ErrorHandler { diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 5d87693247..8ed2ecabd9 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -343,7 +343,7 @@ class Cache extends \PHPUnit_Framework_TestCase { } /** - * @brief this test show the bug resulting if we have no normalizer installed + * this test show the bug resulting if we have no normalizer installed */ public function testWithoutNormalizer() { // folder name "Schön" with U+00F6 (normalized) @@ -386,7 +386,7 @@ class Cache extends \PHPUnit_Framework_TestCase { } /** - * @brief this test shows that there is no bug if we use the normalizer + * this test shows that there is no bug if we use the normalizer */ public function testWithNormalizer() { diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index f80dd06e1c..201eb9ff6c 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -585,4 +585,24 @@ class View extends \PHPUnit_Framework_TestCase { $info2 = $view->getFileInfo('/test/test'); $this->assertSame($info['etag'], $info2['etag']); } + + /** + * @dataProvider absolutePathProvider + */ + public function testGetAbsolutePath($expectedPath, $relativePath) { + $view = new \OC\Files\View('/files'); + $this->assertEquals($expectedPath, $view->getAbsolutePath($relativePath)); + } + + function absolutePathProvider() { + return array( + array('/files/', ''), + array('/files/0', '0'), + array('/files/false', 'false'), + array('/files/true', 'true'), + array('/files/', '/'), + array('/files/test', 'test'), + array('/files/test', '/test'), + ); + } } diff --git a/tests/lib/group.php b/tests/lib/group.php index 8de8d033e1..724e723b18 100644 --- a/tests/lib/group.php +++ b/tests/lib/group.php @@ -4,8 +4,8 @@ * * @author Robin Appelman * @author Bernhard Posselt - * @copyright 2012 Robin Appelman icewind@owncloud.com - * @copyright 2012 Bernhard Posselt nukeawhale@gmail.com + * @copyright 2012 Robin Appelman + * @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -109,25 +109,6 @@ class Test_Group extends PHPUnit_Framework_TestCase { $this->assertEquals(array(), OC_Group::getGroups()); } - public function testDisplayNamesInGroup() { - OC_Group::useBackend(new OC_Group_Dummy()); - $userBackend = new \OC_User_Dummy(); - \OC_User::getManager()->registerBackend($userBackend); - - $group1 = uniqid(); - $user1 = 'uid1'; - $user2 = 'uid2'; - OC_Group::createGroup($group1); - $userBackend->createUser($user1, ''); - $userBackend->createUser($user2, ''); - OC_Group::addToGroup($user1, $group1); - OC_Group::addToGroup($user2, $group1); - //Dummy backend does not support setting displaynames, uid will always - //be returned. This checks primarily, that the return format is okay. - $expected = array($user1 => $user1, $user2 => $user2); - $this->assertEquals($expected, OC_Group::displayNamesInGroup($group1)); - } - public function testUsersInGroup() { OC_Group::useBackend(new OC_Group_Dummy()); $userBackend = new \OC_User_Dummy(); diff --git a/tests/lib/group/group.php b/tests/lib/group/group.php index 990f8ecc1d..4d15999a82 100644 --- a/tests/lib/group/group.php +++ b/tests/lib/group/group.php @@ -17,9 +17,10 @@ class Group extends \PHPUnit_Framework_TestCase { */ protected function getUserManager() { $userManager = $this->getMock('\OC\User\Manager'); - $user1 = new User('user1', null); - $user2 = new User('user2', null); - $user3 = new User('user3', null); + $backend = $this->getMock('\OC_User_Backend'); + $user1 = new User('user1', $backend); + $user2 = new User('user2', $backend); + $user3 = new User('user3', $backend); $userManager->expects($this->any()) ->method('get') ->will($this->returnValueMap(array( @@ -79,6 +80,7 @@ class Group extends \PHPUnit_Framework_TestCase { public function testInGroupSingleBackend() { $backend = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend), $userManager); $backend->expects($this->once()) @@ -86,13 +88,14 @@ class Group extends \PHPUnit_Framework_TestCase { ->with('user1', 'group1') ->will($this->returnValue(true)); - $this->assertTrue($group->inGroup(new User('user1', null))); + $this->assertTrue($group->inGroup(new User('user1', $userBackend))); } public function testInGroupMultipleBackends() { $backend1 = $this->getMock('OC_Group_Database'); $backend2 = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager); $backend1->expects($this->once()) @@ -105,12 +108,13 @@ class Group extends \PHPUnit_Framework_TestCase { ->with('user1', 'group1') ->will($this->returnValue(true)); - $this->assertTrue($group->inGroup(new User('user1', null))); + $this->assertTrue($group->inGroup(new User('user1', $userBackend))); } public function testAddUser() { $backend = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend), $userManager); $backend->expects($this->once()) @@ -125,12 +129,13 @@ class Group extends \PHPUnit_Framework_TestCase { ->method('addToGroup') ->with('user1', 'group1'); - $group->addUser(new User('user1', null)); + $group->addUser(new User('user1', $userBackend)); } public function testAddUserAlreadyInGroup() { $backend = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend), $userManager); $backend->expects($this->once()) @@ -144,12 +149,13 @@ class Group extends \PHPUnit_Framework_TestCase { $backend->expects($this->never()) ->method('addToGroup'); - $group->addUser(new User('user1', null)); + $group->addUser(new User('user1', $userBackend)); } public function testRemoveUser() { $backend = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend), $userManager); $backend->expects($this->once()) @@ -164,12 +170,13 @@ class Group extends \PHPUnit_Framework_TestCase { ->method('removeFromGroup') ->with('user1', 'group1'); - $group->removeUser(new User('user1', null)); + $group->removeUser(new User('user1', $userBackend)); } public function testRemoveUserNotInGroup() { $backend = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend), $userManager); $backend->expects($this->once()) @@ -183,13 +190,14 @@ class Group extends \PHPUnit_Framework_TestCase { $backend->expects($this->never()) ->method('removeFromGroup'); - $group->removeUser(new User('user1', null)); + $group->removeUser(new User('user1', $userBackend)); } public function testRemoveUserMultipleBackends() { $backend1 = $this->getMock('OC_Group_Database'); $backend2 = $this->getMock('OC_Group_Database'); $userManager = $this->getUserManager(); + $userBackend = $this->getMock('\OC_User_Backend'); $group = new \OC\Group\Group('group1', array($backend1, $backend2), $userManager); $backend1->expects($this->once()) @@ -216,7 +224,7 @@ class Group extends \PHPUnit_Framework_TestCase { ->method('removeFromGroup') ->with('user1', 'group1'); - $group->removeUser(new User('user1', null)); + $group->removeUser(new User('user1', $userBackend)); } public function testSearchUsers() { diff --git a/tests/lib/group/manager.php b/tests/lib/group/manager.php index a03997c58e..6799a598d4 100644 --- a/tests/lib/group/manager.php +++ b/tests/lib/group/manager.php @@ -294,10 +294,11 @@ class Manager extends \PHPUnit_Framework_TestCase { * @var \OC\User\Manager $userManager */ $userManager = $this->getMock('\OC\User\Manager'); + $userBackend = $this->getMock('\OC_User_Backend'); $manager = new \OC\Group\Manager($userManager); $manager->addBackend($backend); - $groups = $manager->getUserGroups(new User('user1', null)); + $groups = $manager->getUserGroups(new User('user1', $userBackend)); $this->assertEquals(1, count($groups)); $group1 = $groups[0]; $this->assertEquals('group1', $group1->getGID()); @@ -332,15 +333,163 @@ class Manager extends \PHPUnit_Framework_TestCase { * @var \OC\User\Manager $userManager */ $userManager = $this->getMock('\OC\User\Manager'); + $userBackend = $this->getMock('\OC_User_Backend'); $manager = new \OC\Group\Manager($userManager); $manager->addBackend($backend1); $manager->addBackend($backend2); - $groups = $manager->getUserGroups(new User('user1', null)); + $groups = $manager->getUserGroups(new User('user1', $userBackend)); $this->assertEquals(2, count($groups)); $group1 = $groups[0]; $group2 = $groups[1]; $this->assertEquals('group1', $group1->getGID()); $this->assertEquals('group2', $group2->getGID()); } + + public function testDisplayNamesInGroupMultipleUserBackends() { + $userBackend = $this->getMock('\OC_User_Backend'); + + $user1 = new User('user1', $userBackend); + $user2 = new User('user2', $userBackend); + $user3 = new User('user3', $userBackend); + $user4 = new User('user33', $userBackend); + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend1 + */ + $backend = $this->getMock('\OC_Group_Database'); + $backend->expects($this->exactly(1)) + ->method('groupExists') + ->with('testgroup') + ->will($this->returnValue(true)); + + $backend->expects($this->once()) + ->method('usersInGroup') + ->with('testgroup', '', -1, 0) + ->will($this->returnValue(array('user2', 'user33'))); + + /** + * @var \OC\User\Manager $userManager + */ + $userManager = $this->getMock('\OC\User\Manager'); + $userBackend = $this->getMock('\OC_User_Backend'); + $userManager->expects($this->once()) + ->method('search') + ->with('user3') + ->will($this->returnValue(array('user3' => $user3, 'user33' => $user4))); + + $userManager->expects($this->any()) + ->method('get') + ->will($this->returnCallback(function($uid) use ($userBackend) { + switch($uid) { + case 'user1' : return new User('user1', $userBackend); + case 'user2' : return new User('user2', $userBackend); + case 'user3' : return new User('user3', $userBackend); + case 'user33': return new User('user33', $userBackend); + default: + return null; + } + })); + + $manager = new \OC\Group\Manager($userManager); + $manager->addBackend($backend); + + $users = $manager->displayNamesInGroup('testgroup', 'user3'); + $this->assertEquals(1, count($users)); + $this->assertTrue(isset($users['user33'])); + } + + public function testGetUserGroupsWithAddUser() { + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend + */ + $backend = $this->getMock('\OC_Group_Database'); + $expectedGroups = array(); + $backend->expects($this->any()) + ->method('getUserGroups') + ->with('user1') + ->will($this->returnCallback(function () use (&$expectedGroups) { + return $expectedGroups; + })); + $backend->expects($this->any()) + ->method('groupExists') + ->with('group1') + ->will($this->returnValue(true)); + $backend->expects($this->once()) + ->method('implementsActions') + ->will($this->returnValue(true)); + + /** + * @var \OC\User\Manager $userManager + */ + $userManager = $this->getMock('\OC\User\Manager'); + $manager = new \OC\Group\Manager($userManager); + $manager->addBackend($backend); + + // prime cache + $user1 = new User('user1', null); + $groups = $manager->getUserGroups($user1); + $this->assertEquals(array(), $groups); + + // add user + $group = $manager->get('group1'); + $group->addUser($user1); + $expectedGroups = array('group1'); + + // check result + $groups = $manager->getUserGroups($user1); + $this->assertEquals(1, count($groups)); + $group1 = $groups[0]; + $this->assertEquals('group1', $group1->getGID()); + } + + public function testGetUserGroupsWithRemoveUser() { + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \OC_Group_Backend $backend + */ + $backend = $this->getMock('\OC_Group_Database'); + $expectedGroups = array('group1'); + $backend->expects($this->any()) + ->method('getUserGroups') + ->with('user1') + ->will($this->returnCallback(function () use (&$expectedGroups) { + return $expectedGroups; + })); + $backend->expects($this->any()) + ->method('groupExists') + ->with('group1') + ->will($this->returnValue(true)); + $backend->expects($this->once()) + ->method('implementsActions') + ->will($this->returnValue(true)); + $backend->expects($this->once()) + ->method('inGroup') + ->will($this->returnValue(true)); + $backend->expects($this->once()) + ->method('removeFromGroup') + ->will($this->returnValue(true)); + + /** + * @var \OC\User\Manager $userManager + */ + $userManager = $this->getMock('\OC\User\Manager'); + $manager = new \OC\Group\Manager($userManager); + $manager->addBackend($backend); + + // prime cache + $user1 = new User('user1', null); + $groups = $manager->getUserGroups($user1); + $this->assertEquals(1, count($groups)); + $group1 = $groups[0]; + $this->assertEquals('group1', $group1->getGID()); + + // remove user + $group = $manager->get('group1'); + $group->removeUser($user1); + $expectedGroups = array(); + + // check result + $groups = $manager->getUserGroups($user1); + $this->assertEquals(array(), $groups); + } } diff --git a/tests/lib/helper.php b/tests/lib/helper.php index 4aef4669cb..cfd66e9970 100644 --- a/tests/lib/helper.php +++ b/tests/lib/helper.php @@ -120,15 +120,15 @@ class Test_Helper extends PHPUnit_Framework_TestCase { $this->assertEquals($result, $expected); } - function testIssubdirectory() { - $result = OC_Helper::issubdirectory("./data/", "/anotherDirectory/"); + function testIsSubDirectory() { + $result = OC_Helper::isSubDirectory("./data/", "/anotherDirectory/"); $this->assertFalse($result); - $result = OC_Helper::issubdirectory("./data/", "./data/"); + $result = OC_Helper::isSubDirectory("./data/", "./data/"); $this->assertTrue($result); mkdir("data/TestSubdirectory", 0777); - $result = OC_Helper::issubdirectory("data/TestSubdirectory/", "data"); + $result = OC_Helper::isSubDirectory("data/TestSubdirectory/", "data"); rmdir("data/TestSubdirectory"); $this->assertTrue($result); } @@ -156,7 +156,7 @@ class Test_Helper extends PHPUnit_Framework_TestCase { ); $result = OC_Helper::mb_array_change_key_case($arrayStart, MB_CASE_UPPER); $expected = $arrayResult; - $this->assertEquals($result, $expected); + $this->assertEquals($result, $expected); } function testMb_substr_replace() { @@ -279,4 +279,179 @@ class Test_Helper extends PHPUnit_Framework_TestCase { array(3670, true, \OC::$SERVERROOT . '/tests/data/testimage.png', \OC::$SERVERROOT . '/tests/data/testimage-copy.png'), ); } + + // Url generator methods + + /** + * @small + * test absolute URL construction + * @dataProvider provideDocRootURLs + */ + function testMakeAbsoluteURLDocRoot($url, $expectedResult) { + \OC::$WEBROOT = ''; + $result = \OC_Helper::makeURLAbsolute($url); + + $this->assertEquals($expectedResult, $result); + } + + /** + * @small + * test absolute URL construction + * @dataProvider provideSubDirURLs + */ + function testMakeAbsoluteURLSubDir($url, $expectedResult) { + \OC::$WEBROOT = '/owncloud'; + $result = \OC_Helper::makeURLAbsolute($url); + + $this->assertEquals($expectedResult, $result); + } + + public function provideDocRootURLs() { + return array( + array('index.php', 'http://localhost/index.php'), + array('/index.php', 'http://localhost/index.php'), + array('/apps/index.php', 'http://localhost/apps/index.php'), + array('apps/index.php', 'http://localhost/apps/index.php'), + ); + } + + public function provideSubDirURLs() { + return array( + array('index.php', 'http://localhost/owncloud/index.php'), + array('/index.php', 'http://localhost/owncloud/index.php'), + array('/apps/index.php', 'http://localhost/owncloud/apps/index.php'), + array('apps/index.php', 'http://localhost/owncloud/apps/index.php'), + ); + } + + /** + * @small + * test linkTo URL construction + * @dataProvider provideDocRootAppUrlParts + */ + public function testLinkToDocRoot($app, $file, $args, $expectedResult) { + \OC::$WEBROOT = ''; + $result = \OC_Helper::linkTo($app, $file, $args); + + $this->assertEquals($expectedResult, $result); + } + + /** + * @small + * test linkTo URL construction in sub directory + * @dataProvider provideSubDirAppUrlParts + */ + public function testLinkToSubDir($app, $file, $args, $expectedResult) { + \OC::$WEBROOT = '/owncloud'; + $result = \OC_Helper::linkTo($app, $file, $args); + + $this->assertEquals($expectedResult, $result); + } + + public function provideDocRootAppUrlParts() { + return array( + array('files', 'index.php', array(), '/index.php/apps/files'), + array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php/apps/files?trut=trat&dut=dat'), + array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php?trut=trat&dut=dat'), + ); + } + + public function provideSubDirAppUrlParts() { + return array( + array('files', 'index.php', array(), '/owncloud/index.php/apps/files'), + array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php/apps/files?trut=trat&dut=dat'), + array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php?trut=trat&dut=dat'), + ); + } + + /** + * @small + * test linkToAbsolute URL construction + * @dataProvider provideDocRootAppAbsoluteUrlParts + */ + public function testLinkToAbsoluteDocRoot($app, $file, $args, $expectedResult) { + \OC::$WEBROOT = ''; + $result = \OC_Helper::linkToAbsolute($app, $file, $args); + + $this->assertEquals($expectedResult, $result); + } + + /** + * @small + * test linkToAbsolute URL construction in sub directory + * @dataProvider provideSubDirAppAbsoluteUrlParts + */ + public function testLinkToAbsoluteSubDir($app, $file, $args, $expectedResult) { + \OC::$WEBROOT = '/owncloud'; + $result = \OC_Helper::linkToAbsolute($app, $file, $args); + + $this->assertEquals($expectedResult, $result); + } + + public function provideDocRootAppAbsoluteUrlParts() { + return array( + array('files', 'index.php', array(), 'http://localhost/index.php/apps/files'), + array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/index.php/apps/files?trut=trat&dut=dat'), + array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/index.php?trut=trat&dut=dat'), + ); + } + + public function provideSubDirAppAbsoluteUrlParts() { + return array( + array('files', 'index.php', array(), 'http://localhost/owncloud/index.php/apps/files'), + array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/owncloud/index.php/apps/files?trut=trat&dut=dat'), + array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), 'http://localhost/owncloud/index.php?trut=trat&dut=dat'), + ); + } + + /** + * @small + * test linkToRemoteBase URL construction + */ + public function testLinkToRemoteBase() { + \OC::$WEBROOT = ''; + $result = \OC_Helper::linkToRemoteBase('webdav'); + $this->assertEquals('/remote.php/webdav', $result); + + \OC::$WEBROOT = '/owncloud'; + $result = \OC_Helper::linkToRemoteBase('webdav'); + $this->assertEquals('/owncloud/remote.php/webdav', $result); + } + + /** + * @small + * test linkToRemote URL construction + */ + public function testLinkToRemote() { + \OC::$WEBROOT = ''; + $result = \OC_Helper::linkToRemote('webdav'); + $this->assertEquals('http://localhost/remote.php/webdav/', $result); + $result = \OC_Helper::linkToRemote('webdav', false); + $this->assertEquals('http://localhost/remote.php/webdav', $result); + + \OC::$WEBROOT = '/owncloud'; + $result = \OC_Helper::linkToRemote('webdav'); + $this->assertEquals('http://localhost/owncloud/remote.php/webdav/', $result); + $result = \OC_Helper::linkToRemote('webdav', false); + $this->assertEquals('http://localhost/owncloud/remote.php/webdav', $result); + } + + /** + * @small + * test linkToPublic URL construction + */ + public function testLinkToPublic() { + \OC::$WEBROOT = ''; + $result = \OC_Helper::linkToPublic('files'); + $this->assertEquals('http://localhost/public.php?service=files', $result); + $result = \OC_Helper::linkToPublic('files', false); + $this->assertEquals('http://localhost/public.php?service=files', $result); + + \OC::$WEBROOT = '/owncloud'; + $result = \OC_Helper::linkToPublic('files'); + $this->assertEquals('http://localhost/owncloud/public.php?service=files', $result); + $result = \OC_Helper::linkToPublic('files', false); + $this->assertEquals('http://localhost/owncloud/public.php?service=files', $result); + } + } diff --git a/tests/lib/logger.php b/tests/lib/logger.php new file mode 100644 index 0000000000..7d5d4049b2 --- /dev/null +++ b/tests/lib/logger.php @@ -0,0 +1,40 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test; + +use OC\Log; + +class Logger extends \PHPUnit_Framework_TestCase { + /** + * @var \OCP\ILogger + */ + private $logger; + static private $logs = array(); + + public function setUp() { + self::$logs = array(); + $this->logger = new Log($this); + } + + public function testInterpolation() { + $logger = $this->logger; + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('1 {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + private function getLogs() { + return self::$logs; + } + + public static function write($app, $message, $level) { + self::$logs[]= "$level $message"; + } +} diff --git a/tests/lib/migrate.php b/tests/lib/migrate.php index d438a7a692..c4442511e1 100644 --- a/tests/lib/migrate.php +++ b/tests/lib/migrate.php @@ -12,7 +12,7 @@ class Test_Migrate extends PHPUnit_Framework_TestCase { public $tmpfiles = array(); /** - * @brief Generates a test user and sets up their file system + * Generates a test user and sets up their file system * @return string the test users id */ public function generateUser() { @@ -27,8 +27,8 @@ class Test_Migrate extends PHPUnit_Framework_TestCase { } /** - * @brief validates an export for a user - * @brief checks for existence of export_info.json and file folder + * validates an export for a user + * checks for existence of export_info.json and file folder * @param string $exportedUser the user that was exported * @param string $path the path to the .zip export * @param string $exportedBy diff --git a/tests/lib/tags.php b/tests/lib/tags.php index 97e3734cfd..976b4b4fdc 100644 --- a/tests/lib/tags.php +++ b/tests/lib/tags.php @@ -130,7 +130,7 @@ class Test_Tags extends PHPUnit_Framework_TestCase { $tagger = $this->tagMgr->load($this->objectType); foreach($objids as $id) { - $tagger->tagAs($id, 'Family'); + $this->assertTrue($tagger->tagAs($id, 'Family')); } $this->assertEquals(1, count($tagger->getTags())); diff --git a/tests/lib/template.php b/tests/lib/template.php index eedf688721..819d592aac 100644 --- a/tests/lib/template.php +++ b/tests/lib/template.php @@ -3,7 +3,7 @@ * ownCloud * * @author Bernhard Posselt -* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com +* @copyright 2012 Bernhard Posselt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE diff --git a/tests/lib/urlgenerator.php b/tests/lib/urlgenerator.php index 8e605d88f3..888512ee42 100644 --- a/tests/lib/urlgenerator.php +++ b/tests/lib/urlgenerator.php @@ -8,10 +8,53 @@ class Test_Urlgenerator extends PHPUnit_Framework_TestCase { + /** + * @small + * test linkTo URL construction + * @dataProvider provideDocRootAppUrlParts + */ + public function testLinkToDocRoot($app, $file, $args, $expectedResult) { + \OC::$WEBROOT = ''; + $config = $this->getMock('\OCP\IConfig'); + $urlGenerator = new \OC\URLGenerator($config); + $result = $urlGenerator->linkTo($app, $file, $args); + + $this->assertEquals($expectedResult, $result); + } /** * @small - * @brief test absolute URL construction + * test linkTo URL construction in sub directory + * @dataProvider provideSubDirAppUrlParts + */ + public function testLinkToSubDir($app, $file, $args, $expectedResult) { + \OC::$WEBROOT = '/owncloud'; + $config = $this->getMock('\OCP\IConfig'); + $urlGenerator = new \OC\URLGenerator($config); + $result = $urlGenerator->linkTo($app, $file, $args); + + $this->assertEquals($expectedResult, $result); + } + + public function provideDocRootAppUrlParts() { + return array( + array('files', 'index.php', array(), '/index.php/apps/files'), + array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php/apps/files?trut=trat&dut=dat'), + array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/index.php?trut=trat&dut=dat'), + ); + } + + public function provideSubDirAppUrlParts() { + return array( + array('files', 'index.php', array(), '/owncloud/index.php/apps/files'), + array('files', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php/apps/files?trut=trat&dut=dat'), + array('', 'index.php', array('trut' => 'trat', 'dut' => 'dat'), '/owncloud/index.php?trut=trat&dut=dat'), + ); + } + + /** + * @small + * test absolute URL construction * @dataProvider provideDocRootURLs */ function testGetAbsoluteURLDocRoot($url, $expectedResult) { @@ -25,7 +68,7 @@ class Test_Urlgenerator extends PHPUnit_Framework_TestCase { /** * @small - * @brief test absolute URL construction + * test absolute URL construction * @dataProvider provideSubDirURLs */ function testGetAbsoluteURLSubDir($url, $expectedResult) { diff --git a/tests/lib/user/manager.php b/tests/lib/user/manager.php index 8ca0f94c6f..fd0931af7e 100644 --- a/tests/lib/user/manager.php +++ b/tests/lib/user/manager.php @@ -190,8 +190,8 @@ class Manager extends \PHPUnit_Framework_TestCase { $result = $manager->search('fo'); $this->assertEquals(2, count($result)); - $this->assertEquals('afoo', $result[0]->getUID()); - $this->assertEquals('foo', $result[1]->getUID()); + $this->assertEquals('afoo', array_shift($result)->getUID()); + $this->assertEquals('foo', array_shift($result)->getUID()); } public function testSearchTwoBackendLimitOffset() { @@ -219,9 +219,9 @@ class Manager extends \PHPUnit_Framework_TestCase { $result = $manager->search('fo', 3, 1); $this->assertEquals(3, count($result)); - $this->assertEquals('foo1', $result[0]->getUID()); - $this->assertEquals('foo2', $result[1]->getUID()); - $this->assertEquals('foo3', $result[2]->getUID()); + $this->assertEquals('foo1', array_shift($result)->getUID()); + $this->assertEquals('foo2', array_shift($result)->getUID()); + $this->assertEquals('foo3', array_shift($result)->getUID()); } public function testCreateUserSingleBackendNotExists() {