diff options
143 files changed, 2154 insertions, 722 deletions
diff --git a/apps/encryption/lib/crypto/encryptall.php b/apps/encryption/lib/crypto/encryptall.php index a0c69c13fdd..8e97fe341b4 100644 --- a/apps/encryption/lib/crypto/encryptall.php +++ b/apps/encryption/lib/crypto/encryptall.php @@ -280,6 +280,12 @@ class EncryptAll { $newPasswords[] = [$uid, $password]; } } + + if (empty($newPasswords)) { + $this->output->writeln("\nAll users already had a key-pair, no further action needed.\n"); + return; + } + $table->setRows($newPasswords); $table->render(); diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css index ea9d48b470c..faa26678562 100644 --- a/apps/files/css/detailsView.css +++ b/apps/files/css/detailsView.css @@ -32,12 +32,18 @@ #app-sidebar .image .thumbnail { width:100%; display:block; - height: 250px; background-repeat: no-repeat; background-position: center; background-size: 100%; float: none; margin: 0; + height: auto; +} + +#app-sidebar .image.landscape .thumbnail::before { + content: ''; + display: block; + padding-bottom: 56.25%; /* sets height of .thumbnail to 9/16 of the width */ } #app-sidebar .image.portrait .thumbnail { @@ -71,17 +77,14 @@ #app-sidebar .fileName h3 { max-width: 300px; - float:left; + display: inline-block; padding: 5px 0; margin: -5px 0; } #app-sidebar .file-details { - margin-top: 3px; - margin-bottom: 15px; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; opacity: .5; - float:left; } #app-sidebar .action-favorite { vertical-align: text-bottom; diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js index 3a775c29ec6..b01f9cea610 100644 --- a/apps/files/js/detailsview.js +++ b/apps/files/js/detailsview.js @@ -84,7 +84,7 @@ }, _onClose: function(event) { - OC.Apps.hideAppSidebar(); + OC.Apps.hideAppSidebar(this.$el); event.preventDefault(); }, diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index f3f137a0537..d3904f2f6d3 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -594,6 +594,7 @@ this.registerAction({ name: 'Rename', + displayName: t('files', 'Rename'), mime: 'all', permissions: OC.PERMISSION_UPDATE, icon: function() { @@ -614,6 +615,7 @@ this.registerAction({ name: 'Delete', + displayName: t('files', 'Delete'), mime: 'all', // permission is READ because we show a hint instead if there is no permission permissions: OC.PERMISSION_DELETE, diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 2af5be73d96..ad3dce19778 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -300,12 +300,13 @@ if (this._detailsView) { this.fileActions.registerAction({ name: 'Details', + displayName: t('files', 'Details'), mime: 'all', icon: OC.imagePath('core', 'actions/details'), permissions: OC.PERMISSION_READ, actionHandler: function(fileName, context) { self._updateDetailsView(fileName); - OC.Apps.showAppSidebar(); + OC.Apps.showAppSidebar(self._detailsView.$el); } }); } @@ -380,7 +381,7 @@ if (tabId) { this._detailsView.selectTab(tabId); } - OC.Apps.showAppSidebar(); + OC.Apps.showAppSidebar(this._detailsView.$el); }, /** @@ -924,7 +925,7 @@ if (this._allowSelection) { td.append( '<input id="select-' + this.id + '-' + fileData.id + - '" type="checkbox" class="selectCheckBox"/><label for="select-' + this.id + '-' + fileData.id + '">' + + '" type="checkbox" class="selectCheckBox checkbox"/><label for="select-' + this.id + '-' + fileData.id + '">' + '<div class="thumbnail" style="background-image:url(' + icon + '); background-size: 32px;"></div>' + '<span class="hidden-visually">' + t('files', 'Select') + '</span>' + '</label>' @@ -2536,8 +2537,9 @@ }, _renderNewButton: function() { - // if an upload button (legacy) already exists, skip - if ($('#controls .button.upload').length) { + // if an upload button (legacy) already exists or no actions container exist, skip + var $actionsContainer = this.$el.find('#controls .actions'); + if (!$actionsContainer.length || this.$el.find('.button.upload').length) { return; } if (!this._addButtonTemplate) { @@ -2548,7 +2550,7 @@ iconUrl: OC.imagePath('core', 'actions/add') })); - $('#controls .actions').prepend($newButton); + $actionsContainer.prepend($newButton); $newButton.tooltip({'placement': 'bottom'}); $newButton.click(_.bind(this._onClickNewButton, this)); diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js index 830f074f3f1..82cca0d0fb3 100644 --- a/apps/files/js/mainfileinfodetailview.js +++ b/apps/files/js/mainfileinfodetailview.js @@ -176,9 +176,7 @@ $iconDiv.removeClass('icon-loading icon-32'); var targetHeight = getTargetHeight(img); if (this.model.isImage() && targetHeight > smallPreviewSize) { - if (!isLandscape(img)) { - $container.addClass('portrait'); - } + $container.addClass(isLandscape(img)? 'landscape': 'portrait'); $container.addClass('image'); } @@ -186,7 +184,7 @@ // when we dont have a preview we show the mime icon in the error handler $iconDiv.css({ 'background-image': 'url("' + previewUrl + '")', - 'height': targetHeight + height: (isLandscape(img) && targetHeight > smallPreviewSize)? 'auto': targetHeight }); }.bind(this), error: function () { diff --git a/apps/files/js/tagsplugin.js b/apps/files/js/tagsplugin.js index 9f45da9a6e2..23945d52603 100644 --- a/apps/files/js/tagsplugin.js +++ b/apps/files/js/tagsplugin.js @@ -78,7 +78,7 @@ // register "star" action fileActions.registerAction({ name: 'Favorite', - displayName: 'Favorite', + displayName: t('files', 'Favorite'), mime: 'all', permissions: OC.PERMISSION_READ, type: OCA.Files.FileActions.TYPE_INLINE, diff --git a/apps/files/templates/fileexists.html b/apps/files/templates/fileexists.html index c783f9a05c7..e3513237d2b 100644 --- a/apps/files/templates/fileexists.html +++ b/apps/files/templates/fileexists.html @@ -3,14 +3,14 @@ <span class="what">{what}<!-- If you select both versions, the copied file will have a number added to its name. --></span><br/> <br/> <table> - <th><input id="checkbox-allnewfiles" class="allnewfiles" type="checkbox" /><label for="checkbox-allnewfiles">{allnewfiles}<span class="count"></span></label></th> - <th><input id="checkbox-allexistingfiles" class="allexistingfiles" type="checkbox" /><label for="checkbox-allexistingfiles">{allexistingfiles}<span class="count"></span></label></th> + <th><input id="checkbox-allnewfiles" class="allnewfiles checkbox" type="checkbox" /><label for="checkbox-allnewfiles">{allnewfiles}<span class="count"></span></label></th> + <th><input id="checkbox-allexistingfiles" class="allexistingfiles checkbox" type="checkbox" /><label for="checkbox-allexistingfiles">{allexistingfiles}<span class="count"></span></label></th> </table> <div class="conflicts"> <div class="template"> <div class="filename"></div> <div class="replacement"> - <input type="checkbox" class="u-left"/> + <input type="checkbox" class="checkbox u-left"/> <label> <span class="svg icon"></span> <div class="mtime"></div> @@ -18,7 +18,7 @@ </label> </div> <div class="original"> - <input type="checkbox" class="u-left" /> + <input type="checkbox" class="checkbox u-left" /> <label> <span class="svg icon"></span> <div class="mtime"></div> diff --git a/apps/files/templates/list.php b/apps/files/templates/list.php index 15af1970dc3..bbbce8473de 100644 --- a/apps/files/templates/list.php +++ b/apps/files/templates/list.php @@ -56,7 +56,7 @@ <tr> <th id='headerName' class="hidden column-name"> <div id="headerName-container"> - <input type="checkbox" id="select_all_files" class="select-all"/> + <input type="checkbox" id="select_all_files" class="select-all checkbox"/> <label for="select_all_files"> <span class="hidden-visually"><?php p($l->t('Select all'))?></span> </label> diff --git a/apps/files_external/controller/globalstoragescontroller.php b/apps/files_external/controller/globalstoragescontroller.php index 7d97fdbb4f4..3c1f2022505 100644 --- a/apps/files_external/controller/globalstoragescontroller.php +++ b/apps/files_external/controller/globalstoragescontroller.php @@ -98,7 +98,7 @@ class GlobalStoragesController extends StoragesController { return $newStorage; } - $response = $this->validate($newStorage, BackendService::PERMISSION_CREATE); + $response = $this->validate($newStorage); if (!empty($response)) { return $response; } @@ -154,7 +154,7 @@ class GlobalStoragesController extends StoragesController { } $storage->setId($id); - $response = $this->validate($storage, BackendService::PERMISSION_MODIFY); + $response = $this->validate($storage); if (!empty($response)) { return $response; } @@ -179,14 +179,5 @@ class GlobalStoragesController extends StoragesController { } - /** - * Get the user type for this controller, used in validation - * - * @return string BackendService::USER_* constants - */ - protected function getUserType() { - return BackendService::USER_ADMIN; - } - } diff --git a/apps/files_external/controller/storagescontroller.php b/apps/files_external/controller/storagescontroller.php index 46202c8ba4a..6a01112f8c5 100644 --- a/apps/files_external/controller/storagescontroller.php +++ b/apps/files_external/controller/storagescontroller.php @@ -125,11 +125,10 @@ abstract class StoragesController extends Controller { * Validate storage config * * @param StorageConfig $storage storage config - * @param int $permissionCheck permission to check * * @return DataResponse|null returns response in case of validation error */ - protected function validate(StorageConfig $storage, $permissionCheck = BackendService::PERMISSION_CREATE) { + protected function validate(StorageConfig $storage) { $mountPoint = $storage->getMountPoint(); if ($mountPoint === '' || $mountPoint === '/') { return new DataResponse( @@ -154,7 +153,7 @@ abstract class StoragesController extends Controller { $backend = $storage->getBackend(); /** @var AuthMechanism */ $authMechanism = $storage->getAuthMechanism(); - if (!$backend || $backend->checkDependencies()) { + if ($backend->checkDependencies()) { // invalid backend return new DataResponse( array( @@ -166,7 +165,7 @@ abstract class StoragesController extends Controller { ); } - if (!$backend->isPermitted($this->getUserType(), $permissionCheck)) { + if (!$backend->isVisibleFor($this->service->getVisibilityType())) { // not permitted to use backend return new DataResponse( array( @@ -177,7 +176,7 @@ abstract class StoragesController extends Controller { Http::STATUS_UNPROCESSABLE_ENTITY ); } - if (!$authMechanism->isPermitted($this->getUserType(), $permissionCheck)) { + if (!$authMechanism->isVisibleFor($this->service->getVisibilityType())) { // not permitted to use auth mechanism return new DataResponse( array( @@ -212,13 +211,6 @@ abstract class StoragesController extends Controller { } /** - * Get the user type for this controller, used in validation - * - * @return string BackendService::USER_* constants - */ - abstract protected function getUserType(); - - /** * Check whether the given storage is available / valid. * * Note that this operation can be time consuming depending diff --git a/apps/files_external/controller/userstoragescontroller.php b/apps/files_external/controller/userstoragescontroller.php index 801c9ab0aae..f39f8a85d2d 100644 --- a/apps/files_external/controller/userstoragescontroller.php +++ b/apps/files_external/controller/userstoragescontroller.php @@ -103,7 +103,7 @@ class UserStoragesController extends StoragesController { return $newStorage; } - $response = $this->validate($newStorage, BackendService::PERMISSION_CREATE); + $response = $this->validate($newStorage); if (!empty($response)) { return $response; } @@ -151,7 +151,7 @@ class UserStoragesController extends StoragesController { } $storage->setId($id); - $response = $this->validate($storage, BackendService::PERMISSION_MODIFY); + $response = $this->validate($storage); if (!empty($response)) { return $response; } @@ -187,13 +187,4 @@ class UserStoragesController extends StoragesController { return parent::destroy($id); } - /** - * Get the user type for this controller, used in validation - * - * @return string BackendService::USER_* constants - */ - protected function getUserType() { - return BackendService::USER_PERSONAL; - } - } diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 4319677f4f4..5da34c52193 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -1113,7 +1113,18 @@ $(document).ready(function() { $('input[name="allowUserMountingBackends\\[\\]"]').bind('change', function() { OC.msg.startSaving('#userMountingMsg'); - var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){return $(this).val();}).get(); + + var userMountingBackends = $('input[name="allowUserMountingBackends\\[\\]"]:checked').map(function(){ + return $(this).val(); + }).get(); + var deprecatedBackends = $('input[name="allowUserMountingBackends\\[\\]"][data-deprecate-to]').map(function(){ + if ($.inArray($(this).data('deprecate-to'), userMountingBackends) !== -1) { + return $(this).val(); + } + return null; + }).get(); + userMountingBackends = userMountingBackends.concat(deprecatedBackends); + OC.AppConfig.setValue('files_external', 'user_mounting_backends', userMountingBackends.join()); OC.msg.finishedSaving('#userMountingMsg', {status: 'success', data: {message: t('files_external', 'Saved')}}); diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 34e8974a6d5..24a0346df63 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -517,7 +517,7 @@ class AmazonS3 extends \OC\Files\Storage\Common { $dh = $this->opendir($path1); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { - if ($file === '.' || $file === '..') { + if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } diff --git a/apps/files_external/lib/auth/authmechanism.php b/apps/files_external/lib/auth/authmechanism.php index ddc0c6a4dca..2ab34ed0105 100644 --- a/apps/files_external/lib/auth/authmechanism.php +++ b/apps/files_external/lib/auth/authmechanism.php @@ -22,7 +22,7 @@ namespace OCA\Files_External\Lib\Auth; use \OCA\Files_External\Lib\StorageConfig; -use \OCA\Files_External\Lib\PermissionsTrait; +use \OCA\Files_External\Lib\VisibilityTrait; use \OCA\Files_External\Lib\IdentifierTrait; use \OCA\Files_External\Lib\FrontendDefinitionTrait; use \OCA\Files_External\Lib\StorageModifierTrait; @@ -40,7 +40,7 @@ use \OCA\Files_External\Lib\StorageModifierTrait; * scheme, which are provided from the authentication mechanism. * * This class uses the following traits: - * - PermissionsTrait + * - VisibilityTrait * Restrict usage to admin-only/none * - FrontendDefinitionTrait * Specify configuration parameters and other definitions @@ -58,7 +58,7 @@ class AuthMechanism implements \JsonSerializable { const SCHEME_PUBLICKEY = 'publickey'; const SCHEME_OPENSTACK = 'openstack'; - use PermissionsTrait; + use VisibilityTrait; use FrontendDefinitionTrait; use StorageModifierTrait; use IdentifierTrait; @@ -92,6 +92,8 @@ class AuthMechanism implements \JsonSerializable { */ public function jsonSerialize() { $data = $this->jsonSerializeDefinition(); + $data += $this->jsonSerializeIdentifier(); + $data['scheme'] = $this->getScheme(); return $data; diff --git a/apps/files_external/lib/backend/backend.php b/apps/files_external/lib/backend/backend.php index 2a2add3ac59..68585cf377e 100644 --- a/apps/files_external/lib/backend/backend.php +++ b/apps/files_external/lib/backend/backend.php @@ -22,7 +22,7 @@ namespace OCA\Files_External\Lib\Backend; use \OCA\Files_External\Lib\StorageConfig; -use \OCA\Files_External\Lib\PermissionsTrait; +use \OCA\Files_External\Lib\VisibilityTrait; use \OCA\Files_External\Lib\FrontendDefinitionTrait; use \OCA\Files_External\Lib\PriorityTrait; use \OCA\Files_External\Lib\DependencyTrait; @@ -43,7 +43,7 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism; * scheme, which are provided from the authentication mechanism. * * This class uses the following traits: - * - PermissionsTrait + * - VisibilityTrait * Restrict usage to admin-only/none * - FrontendDefinitionTrait * Specify configuration parameters and other definitions @@ -56,7 +56,7 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism; */ class Backend implements \JsonSerializable { - use PermissionsTrait; + use VisibilityTrait; use FrontendDefinitionTrait; use PriorityTrait; use DependencyTrait; @@ -142,6 +142,7 @@ class Backend implements \JsonSerializable { */ public function jsonSerialize() { $data = $this->jsonSerializeDefinition(); + $data += $this->jsonSerializeIdentifier(); $data['backend'] = $data['name']; // legacy compat $data['priority'] = $this->getPriority(); diff --git a/apps/files_external/lib/backend/local.php b/apps/files_external/lib/backend/local.php index a6635491b6e..a80b437fab7 100644 --- a/apps/files_external/lib/backend/local.php +++ b/apps/files_external/lib/backend/local.php @@ -39,7 +39,7 @@ class Local extends Backend { ->addParameters([ (new DefinitionParameter('datadir', $l->t('Location'))), ]) - ->setAllowedPermissions(BackendService::USER_PERSONAL, BackendService::PERMISSION_NONE) + ->setAllowedVisibility(BackendService::VISIBILITY_ADMIN) ->setPriority(BackendService::PRIORITY_DEFAULT + 50) ->addAuthScheme(AuthMechanism::SCHEME_NULL) ->setLegacyAuthMechanism($legacyAuth) diff --git a/apps/files_external/lib/backend/sftp_key.php b/apps/files_external/lib/backend/sftp_key.php index 6a75172026d..13f45f1140c 100644 --- a/apps/files_external/lib/backend/sftp_key.php +++ b/apps/files_external/lib/backend/sftp_key.php @@ -27,23 +27,23 @@ use \OCA\Files_External\Lib\DefinitionParameter; use \OCA\Files_External\Lib\Auth\AuthMechanism; use \OCA\Files_External\Service\BackendService; use \OCA\Files_External\Lib\Auth\PublicKey\RSA; +use \OCA\Files_External\Lib\Backend\SFTP; class SFTP_Key extends Backend { - public function __construct(IL10N $l, RSA $legacyAuth) { + public function __construct(IL10N $l, RSA $legacyAuth, SFTP $sftpBackend) { $this ->setIdentifier('\OC\Files\Storage\SFTP_Key') ->setStorageClass('\OC\Files\Storage\SFTP') - ->setText($l->t('SFTP with secret key login [DEPRECATED]')) + ->setText($l->t('SFTP with secret key login')) ->addParameters([ (new DefinitionParameter('host', $l->t('Host'))), (new DefinitionParameter('root', $l->t('Remote subfolder'))) ->setFlag(DefinitionParameter::FLAG_OPTIONAL), ]) - ->removeAllowedPermission(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE) - ->removeAllowedPermission(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE) ->addAuthScheme(AuthMechanism::SCHEME_PUBLICKEY) ->setLegacyAuthMechanism($legacyAuth) + ->deprecateTo($sftpBackend) ; } diff --git a/apps/files_external/lib/backend/smb_oc.php b/apps/files_external/lib/backend/smb_oc.php index d21b0ddaf42..9fc17400884 100644 --- a/apps/files_external/lib/backend/smb_oc.php +++ b/apps/files_external/lib/backend/smb_oc.php @@ -29,6 +29,7 @@ use \OCA\Files_External\Service\BackendService; use \OCA\Files_External\Lib\Auth\Password\SessionCredentials; use \OCA\Files_External\Lib\StorageConfig; use \OCA\Files_External\Lib\LegacyDependencyCheckPolyfill; +use \OCA\Files_External\Lib\Backend\SMB; /** * Deprecated SMB_OC class - use SMB with the password::sessioncredentials auth mechanism @@ -37,11 +38,11 @@ class SMB_OC extends Backend { use LegacyDependencyCheckPolyfill; - public function __construct(IL10N $l, SessionCredentials $legacyAuth) { + public function __construct(IL10N $l, SessionCredentials $legacyAuth, SMB $smbBackend) { $this ->setIdentifier('\OC\Files\Storage\SMB_OC') ->setStorageClass('\OC\Files\Storage\SMB') - ->setText($l->t('SMB / CIFS using OC login [DEPRECATED]')) + ->setText($l->t('SMB / CIFS using OC login')) ->addParameters([ (new DefinitionParameter('host', $l->t('Host'))), (new DefinitionParameter('username_as_share', $l->t('Username as share'))) @@ -51,11 +52,10 @@ class SMB_OC extends Backend { (new DefinitionParameter('root', $l->t('Remote subfolder'))) ->setFlag(DefinitionParameter::FLAG_OPTIONAL), ]) - ->removeAllowedPermission(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE) - ->removeAllowedPermission(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE) ->setPriority(BackendService::PRIORITY_DEFAULT - 10) ->addAuthScheme(AuthMechanism::SCHEME_PASSWORD) ->setLegacyAuthMechanism($legacyAuth) + ->deprecateTo($smbBackend) ; } diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 2dc7de30a6c..afea7ead4e6 100644 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -112,7 +112,7 @@ class OC_Mount_Config { * @param string $uid user * @return array of mount point string as key, mountpoint config as value * - * @deprecated 8.2.0 use UserGlobalStoragesService::getAllStorages() and UserStoragesService::getAllStorages() + * @deprecated 8.2.0 use UserGlobalStoragesService::getStorages() and UserStoragesService::getStorages() */ public static function getAbsoluteMountPoints($uid) { $mountPoints = array(); @@ -124,7 +124,7 @@ class OC_Mount_Config { $userGlobalStoragesService->setUser($user); $userStoragesService->setUser($user); - foreach ($userGlobalStoragesService->getAllStorages() as $storage) { + foreach ($userGlobalStoragesService->getStorages() as $storage) { $mountPoint = '/'.$uid.'/files'.$storage->getMountPoint(); $mountEntry = self::prepareMountPointEntry($storage, false); foreach ($mountEntry['options'] as &$option) { @@ -133,7 +133,7 @@ class OC_Mount_Config { $mountPoints[$mountPoint] = $mountEntry; } - foreach ($userStoragesService->getAllStorages() as $storage) { + foreach ($userStoragesService->getStorages() as $storage) { $mountPoint = '/'.$uid.'/files'.$storage->getMountPoint(); $mountEntry = self::prepareMountPointEntry($storage, true); foreach ($mountEntry['options'] as &$option) { @@ -153,13 +153,13 @@ class OC_Mount_Config { * * @return array * - * @deprecated 8.2.0 use GlobalStoragesService::getAllStorages() + * @deprecated 8.2.0 use GlobalStoragesService::getStorages() */ public static function getSystemMountPoints() { $mountPoints = []; $service = self::$app->getContainer()->query('OCA\Files_External\Service\GlobalStoragesService'); - foreach ($service->getAllStorages() as $storage) { + foreach ($service->getStorages() as $storage) { $mountPoints[] = self::prepareMountPointEntry($storage, false); } @@ -171,13 +171,13 @@ class OC_Mount_Config { * * @return array * - * @deprecated 8.2.0 use UserStoragesService::getAllStorages() + * @deprecated 8.2.0 use UserStoragesService::getStorages() */ public static function getPersonalMountPoints() { $mountPoints = []; $service = self::$app->getContainer()->query('OCA\Files_External\Service\UserStoragesService'); - foreach ($service->getAllStorages() as $storage) { + foreach ($service->getStorages() as $storage) { $mountPoints[] = self::prepareMountPointEntry($storage, true); } diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php index cb8c2f24caa..fb36e011655 100644 --- a/apps/files_external/lib/config/configadapter.php +++ b/apps/files_external/lib/config/configadapter.php @@ -133,7 +133,7 @@ class ConfigAdapter implements IMountProvider { $mounts[$storage->getMountPoint()] = $mount; } - foreach ($this->userStoragesService->getAllStorages() as $storage) { + foreach ($this->userStoragesService->getStorages() as $storage) { try { $this->prepareStorageConfig($storage, $user); $impl = $this->constructStorage($storage); diff --git a/apps/files_external/lib/identifiertrait.php b/apps/files_external/lib/identifiertrait.php index 139911580fc..7f36144e474 100644 --- a/apps/files_external/lib/identifiertrait.php +++ b/apps/files_external/lib/identifiertrait.php @@ -23,6 +23,7 @@ namespace OCA\Files_External\Lib; /** * Trait for objects requiring an identifier (and/or identifier aliases) + * Also supports deprecation to a different object, linking the objects */ trait IdentifierTrait { @@ -32,6 +33,9 @@ trait IdentifierTrait { /** @var string[] */ protected $identifierAliases = []; + /** @var IdentifierTrait */ + protected $deprecateTo = null; + /** * @return string */ @@ -65,4 +69,34 @@ trait IdentifierTrait { return $this; } + /** + * @return object|null + */ + public function getDeprecateTo() { + return $this->deprecateTo; + } + + /** + * @param object $destinationObject + * @return self + */ + public function deprecateTo($destinationObject) { + $this->deprecateTo = $destinationObject; + return $this; + } + + /** + * @return array + */ + public function jsonSerializeIdentifier() { + $data = [ + 'identifier' => $this->identifier, + 'identifierAliases' => $this->identifierAliases, + ]; + if ($this->deprecateTo) { + $data['deprecateTo'] = $this->deprecateTo->getIdentifier(); + } + return $data; + } + } diff --git a/apps/files_external/lib/permissionstrait.php b/apps/files_external/lib/permissionstrait.php deleted file mode 100644 index 8509a01e422..00000000000 --- a/apps/files_external/lib/permissionstrait.php +++ /dev/null @@ -1,164 +0,0 @@ -<?php -/** - * @author Robin McCorkell <rmccorkell@karoshi.org.uk> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Files_External\Lib; - -use \OCA\Files_External\Service\BackendService; - -/** - * Trait to implement backend and auth mechanism permissions - * - * For user type constants, see BackendService::USER_* - * For permission constants, see BackendService::PERMISSION_* - */ -trait PermissionsTrait { - - /** @var array [user type => permissions] */ - protected $permissions = [ - BackendService::USER_PERSONAL => BackendService::PERMISSION_DEFAULT, - BackendService::USER_ADMIN => BackendService::PERMISSION_DEFAULT, - ]; - - /** @var array [user type => allowed permissions] */ - protected $allowedPermissions = [ - BackendService::USER_PERSONAL => BackendService::PERMISSION_DEFAULT, - BackendService::USER_ADMIN => BackendService::PERMISSION_DEFAULT, - ]; - - /** - * @param string $userType - * @return int - */ - public function getPermissions($userType) { - if (isset($this->permissions[$userType])) { - return $this->permissions[$userType]; - } - return BackendService::PERMISSION_NONE; - } - - /** - * Check if the user type has permission - * - * @param string $userType - * @param int $permission - * @return bool - */ - public function isPermitted($userType, $permission) { - if ($this->getPermissions($userType) & $permission) { - return true; - } - return false; - } - - /** - * @param string $userType - * @param int $permissions - * @return self - */ - public function setPermissions($userType, $permissions) { - $this->permissions[$userType] = $permissions; - $this->allowedPermissions[$userType] = - $this->getAllowedPermissions($userType) | $permissions; - return $this; - } - - /** - * @param string $userType - * @param int $permission - * @return self - */ - public function addPermission($userType, $permission) { - return $this->setPermissions($userType, - $this->getPermissions($userType) | $permission - ); - } - - /** - * @param string $userType - * @param int $permission - * @return self - */ - public function removePermission($userType, $permission) { - return $this->setPermissions($userType, - $this->getPermissions($userType) & ~$permission - ); - } - - /** - * @param string $userType - * @return int - */ - public function getAllowedPermissions($userType) { - if (isset($this->allowedPermissions[$userType])) { - return $this->allowedPermissions[$userType]; - } - return BackendService::PERMISSION_NONE; - } - - /** - * Check if the user type has an allowed permission - * - * @param string $userType - * @param int $permission - * @return bool - */ - public function isAllowedPermitted($userType, $permission) { - if ($this->getAllowedPermissions($userType) & $permission) { - return true; - } - return false; - } - - /** - * @param string $userType - * @param int $permissions - * @return self - */ - public function setAllowedPermissions($userType, $permissions) { - $this->allowedPermissions[$userType] = $permissions; - $this->permissions[$userType] = - $this->getPermissions($userType) & $permissions; - return $this; - } - - /** - * @param string $userType - * @param int $permission - * @return self - */ - public function addAllowedPermission($userType, $permission) { - return $this->setAllowedPermissions($userType, - $this->getAllowedPermissions($userType) | $permission - ); - } - - /** - * @param string $userType - * @param int $permission - * @return self - */ - public function removeAllowedPermission($userType, $permission) { - return $this->setAllowedPermissions($userType, - $this->getAllowedPermissions($userType) & ~$permission - ); - } - -} diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index 6f93f3c84cd..20d2b8f4988 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -175,7 +175,7 @@ class Swift extends \OC\Files\Storage\Common { $dh = $this->opendir($path); while ($file = readdir($dh)) { - if ($file === '.' || $file === '..') { + if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } @@ -429,7 +429,7 @@ class Swift extends \OC\Files\Storage\Common { $dh = $this->opendir($path1); while ($file = readdir($dh)) { - if ($file === '.' || $file === '..') { + if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } diff --git a/apps/files_external/lib/visibilitytrait.php b/apps/files_external/lib/visibilitytrait.php new file mode 100644 index 00000000000..dfd2d323ca6 --- /dev/null +++ b/apps/files_external/lib/visibilitytrait.php @@ -0,0 +1,136 @@ +<?php +/** + * @author Robin McCorkell <rmccorkell@karoshi.org.uk> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\Files_External\Lib; + +use \OCA\Files_External\Service\BackendService; + +/** + * Trait to implement visibility mechanics for a configuration class + * + * The standard visibility defines which users/groups can use or see the + * object. The allowed visibility defines the maximum visibility allowed to be + * set on the object. The standard visibility is often set dynamically by + * stored configuration parameters that can be modified by the administrator, + * while the allowed visibility is set directly by the object and cannot be + * modified by the administrator. + */ +trait VisibilityTrait { + + /** @var int visibility */ + protected $visibility = BackendService::VISIBILITY_DEFAULT; + + /** @var int allowed visibilities */ + protected $allowedVisibility = BackendService::VISIBILITY_DEFAULT; + + /** + * @return int + */ + public function getVisibility() { + return $this->visibility; + } + + /** + * Check if the backend is visible for a user type + * + * @param int $visibility + * @return bool + */ + public function isVisibleFor($visibility) { + if ($this->visibility & $visibility) { + return true; + } + return false; + } + + /** + * @param int $visibility + * @return self + */ + public function setVisibility($visibility) { + $this->visibility = $visibility; + $this->allowedVisibility |= $visibility; + return $this; + } + + /** + * @param int $visibility + * @return self + */ + public function addVisibility($visibility) { + return $this->setVisibility($this->visibility | $visibility); + } + + /** + * @param int $visibility + * @return self + */ + public function removeVisibility($visibility) { + return $this->setVisibility($this->visibility & ~$visibility); + } + + /** + * @return int + */ + public function getAllowedVisibility() { + return $this->allowedVisibility; + } + + /** + * Check if the backend is allowed to be visible for a user type + * + * @param int $allowedVisibility + * @return bool + */ + public function isAllowedVisibleFor($allowedVisibility) { + if ($this->allowedVisibility & $allowedVisibility) { + return true; + } + return false; + } + + /** + * @param int $allowedVisibility + * @return self + */ + public function setAllowedVisibility($allowedVisibility) { + $this->allowedVisibility = $allowedVisibility; + $this->visibility &= $allowedVisibility; + return $this; + } + + /** + * @param int $allowedVisibility + * @return self + */ + public function addAllowedVisibility($allowedVisibility) { + return $this->setAllowedVisibility($this->allowedVisibility | $allowedVisibility); + } + + /** + * @param int $allowedVisibility + * @return self + */ + public function removeAllowedVisibility($allowedVisibility) { + return $this->setAllowedVisibility($this->allowedVisibility & ~$allowedVisibility); + } + +} diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php index d47f983b357..f048d65540b 100644 --- a/apps/files_external/personal.php +++ b/apps/files_external/personal.php @@ -35,10 +35,10 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addStyle('files_external', 'settings'); $backends = array_filter($backendService->getAvailableBackends(), function($backend) { - return $backend->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE); + return $backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL); }); $authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) { - return $authMechanism->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE); + return $authMechanism->isVisibleFor(BackendService::VISIBILITY_PERSONAL); }); foreach ($backends as $backend) { if ($backend->getCustomJs()) { @@ -54,7 +54,7 @@ foreach ($authMechanisms as $authMechanism) { $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled()); $tmpl->assign('isAdminPage', false); -$tmpl->assign('storages', $userStoragesService->getAllStorages()); +$tmpl->assign('storages', $userStoragesService->getStorages()); $tmpl->assign('dependencies', OC_Mount_Config::dependencyMessage($backendService->getBackends())); $tmpl->assign('backends', $backends); $tmpl->assign('authMechanisms', $authMechanisms); diff --git a/apps/files_external/service/backendservice.php b/apps/files_external/service/backendservice.php index 70cb9291660..1e90247b3e4 100644 --- a/apps/files_external/service/backendservice.php +++ b/apps/files_external/service/backendservice.php @@ -31,17 +31,13 @@ use \OCA\Files_External\Lib\Auth\AuthMechanism; */ class BackendService { - /** Permission constants for PermissionsTrait */ - const PERMISSION_NONE = 0; - const PERMISSION_MOUNT = 1; - const PERMISSION_CREATE = 2; - const PERMISSION_MODIFY = 4; + /** Visibility constants for VisibilityTrait */ + const VISIBILITY_NONE = 0; + const VISIBILITY_PERSONAL = 1; + const VISIBILITY_ADMIN = 2; + //const VISIBILITY_ALIENS = 4; - const PERMISSION_DEFAULT = 7; // MOUNT | CREATE | MODIFY - - /** User contants */ - const USER_ADMIN = 'admin'; - const USER_PERSONAL = 'personal'; + const VISIBILITY_DEFAULT = 3; // PERSONAL | ADMIN /** Priority constants for PriorityTrait */ const PRIORITY_DEFAULT = 100; @@ -85,7 +81,7 @@ class BackendService { */ public function registerBackend(Backend $backend) { if (!$this->isAllowedUserBackend($backend)) { - $backend->removePermission(self::USER_PERSONAL, self::PERMISSION_CREATE | self::PERMISSION_MOUNT); + $backend->removeVisibility(BackendService::VISIBILITY_PERSONAL); } foreach ($backend->getIdentifierAliases() as $alias) { $this->backends[$alias] = $backend; @@ -107,7 +103,7 @@ class BackendService { */ public function registerAuthMechanism(AuthMechanism $authMech) { if (!$this->isAllowedAuthMechanism($authMech)) { - $authMech->removePermission(self::USER_PERSONAL, self::PERMISSION_CREATE | self::PERMISSION_MOUNT); + $authMech->removeVisibility(BackendService::VISIBILITY_PERSONAL); } foreach ($authMech->getIdentifierAliases() as $alias) { $this->authMechanisms[$alias] = $authMech; diff --git a/apps/files_external/service/globalstoragesservice.php b/apps/files_external/service/globalstoragesservice.php index 0e2d3f2b9c1..49ffea43d1b 100644 --- a/apps/files_external/service/globalstoragesservice.php +++ b/apps/files_external/service/globalstoragesservice.php @@ -210,4 +210,13 @@ class GlobalStoragesService extends StoragesService { ); } } + + /** + * Get the visibility type for this controller, used in validation + * + * @return string BackendService::VISIBILITY_* constants + */ + public function getVisibilityType() { + return BackendService::VISIBILITY_ADMIN; + } } diff --git a/apps/files_external/service/storagesservice.php b/apps/files_external/service/storagesservice.php index 703f277d84e..83a82de0bed 100644 --- a/apps/files_external/service/storagesservice.php +++ b/apps/files_external/service/storagesservice.php @@ -29,6 +29,8 @@ use \OC\Files\Filesystem; use \OCA\Files_external\Lib\StorageConfig; use \OCA\Files_external\NotFoundException; use \OCA\Files_External\Service\BackendService; +use \OCA\Files_External\Lib\Backend\Backend; +use \OCA\Files_External\Lib\Auth\AuthMechanism; /** * Service class to manage external storages @@ -331,7 +333,7 @@ abstract class StoragesService { } /** - * Gets all storages + * Gets all storages, valid or not * * @return array array of storage configs */ @@ -340,6 +342,47 @@ abstract class StoragesService { } /** + * Gets all valid storages + * + * @return array + */ + public function getStorages() { + return array_filter($this->getAllStorages(), [$this, 'validateStorage']); + } + + /** + * Validate storage + * FIXME: De-duplicate with StoragesController::validate() + * + * @param StorageConfig $storage + * @return bool + */ + protected function validateStorage(StorageConfig $storage) { + /** @var Backend */ + $backend = $storage->getBackend(); + /** @var AuthMechanism */ + $authMechanism = $storage->getAuthMechanism(); + + if (!$backend->isVisibleFor($this->getVisibilityType())) { + // not permitted to use backend + return false; + } + if (!$authMechanism->isVisibleFor($this->getVisibilityType())) { + // not permitted to use auth mechanism + return false; + } + + return true; + } + + /** + * Get the visibility type for this controller, used in validation + * + * @return string BackendService::VISIBILITY_* constants + */ + abstract public function getVisibilityType(); + + /** * Add new storage to the configuration * * @param array $newStorage storage attributes diff --git a/apps/files_external/service/userglobalstoragesservice.php b/apps/files_external/service/userglobalstoragesservice.php index b60473f131e..7c60bc6d497 100644 --- a/apps/files_external/service/userglobalstoragesservice.php +++ b/apps/files_external/service/userglobalstoragesservice.php @@ -117,7 +117,7 @@ class UserGlobalStoragesService extends GlobalStoragesService { * @return StorageConfig[] */ public function getUniqueStorages() { - $storages = $this->getAllStorages(); + $storages = $this->getStorages(); $storagesByMountpoint = []; foreach ($storages as $storage) { diff --git a/apps/files_external/service/userstoragesservice.php b/apps/files_external/service/userstoragesservice.php index c69b8d4f51e..6e3c327c09c 100644 --- a/apps/files_external/service/userstoragesservice.php +++ b/apps/files_external/service/userstoragesservice.php @@ -171,4 +171,13 @@ class UserStoragesService extends StoragesService { $this->triggerHooks($newStorage, Filesystem::signal_create_mount); } } + + /** + * Get the visibility type for this controller, used in validation + * + * @return string BackendService::VISIBILITY_* constants + */ + public function getVisibilityType() { + return BackendService::VISIBILITY_PERSONAL; + } } diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php index 840f1325fb5..f82ab035c1c 100644 --- a/apps/files_external/settings.php +++ b/apps/files_external/settings.php @@ -42,10 +42,10 @@ OCP\Util::addStyle('files_external', 'settings'); \OC_Util::addVendorStyle('select2/select2'); $backends = array_filter($backendService->getAvailableBackends(), function($backend) { - return $backend->isPermitted(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE); + return $backend->isVisibleFor(BackendService::VISIBILITY_ADMIN); }); $authMechanisms = array_filter($backendService->getAuthMechanisms(), function($authMechanism) { - return $authMechanism->isPermitted(BackendService::USER_ADMIN, BackendService::PERMISSION_CREATE); + return $authMechanism->isVisibleFor(BackendService::VISIBILITY_ADMIN); }); foreach ($backends as $backend) { if ($backend->getCustomJs()) { @@ -59,15 +59,13 @@ foreach ($authMechanisms as $authMechanism) { } $userBackends = array_filter($backendService->getAvailableBackends(), function($backend) { - return $backend->isAllowedPermitted( - BackendService::USER_PERSONAL, BackendService::PERMISSION_MOUNT - ); + return $backend->isAllowedVisibleFor(BackendService::VISIBILITY_PERSONAL); }); $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('encryptionEnabled', \OC::$server->getEncryptionManager()->isEnabled()); $tmpl->assign('isAdminPage', true); -$tmpl->assign('storages', $globalStoragesService->getAllStorages()); +$tmpl->assign('storages', $globalStoragesService->getStorages()); $tmpl->assign('backends', $backends); $tmpl->assign('authMechanisms', $authMechanisms); $tmpl->assign('userBackends', $userBackends); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index 7762ff60333..141994d0050 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -157,6 +157,7 @@ }); ?> <?php foreach ($sortedBackends as $backend): ?> + <?php if ($backend->getDeprecateTo()) continue; // ignore deprecated backends ?> <option value="<?php p($backend->getIdentifier()); ?>"><?php p($backend->getText()); ?></option> <?php endforeach; ?> </select> @@ -197,8 +198,12 @@ <p id="userMountingBackends"<?php if ($_['allowUserMounting'] != 'yes'): ?> class="hidden"<?php endif; ?>> <?php p($l->t('Allow users to mount the following external storage')); ?><br /> <?php $i = 0; foreach ($_['userBackends'] as $backend): ?> - <input type="checkbox" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" <?php if ($backend->isPermitted(BackendService::USER_PERSONAL, BackendService::PERMISSION_MOUNT)) print_unescaped(' checked="checked"'); ?> /> - <label for="allowUserMountingBackends<?php p($i); ?>"><?php p($backend->getText()); ?></label> <br /> + <?php if ($deprecateTo = $backend->getDeprecateTo()): ?> + <input type="hidden" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" data-deprecate-to="<?php p($deprecateTo->getIdentifier()); ?>" /> + <?php else: ?> + <input type="checkbox" id="allowUserMountingBackends<?php p($i); ?>" name="allowUserMountingBackends[]" value="<?php p($backend->getIdentifier()); ?>" <?php if ($backend->isVisibleFor(BackendService::VISIBILITY_PERSONAL)) print_unescaped(' checked="checked"'); ?> /> + <label for="allowUserMountingBackends<?php p($i); ?>"><?php p($backend->getText()); ?></label> <br /> + <?php endif; ?> <?php $i++; ?> <?php endforeach; ?> </p> diff --git a/apps/files_external/tests/controller/globalstoragescontrollertest.php b/apps/files_external/tests/controller/globalstoragescontrollertest.php index e1bfad8caf6..6b020198bd8 100644 --- a/apps/files_external/tests/controller/globalstoragescontrollertest.php +++ b/apps/files_external/tests/controller/globalstoragescontrollertest.php @@ -24,6 +24,7 @@ use \OCA\Files_external\Controller\GlobalStoragesController; use \OCA\Files_external\Service\GlobalStoragesService; use \OCP\AppFramework\Http; use \OCA\Files_external\NotFoundException; +use \OCA\Files_External\Service\BackendService; class GlobalStoragesControllerTest extends StoragesControllerTest { public function setUp() { @@ -32,6 +33,9 @@ class GlobalStoragesControllerTest extends StoragesControllerTest { ->disableOriginalConstructor() ->getMock(); + $this->service->method('getVisibilityType') + ->willReturn(BackendService::VISIBILITY_ADMIN); + $this->controller = new GlobalStoragesController( 'files_external', $this->getMock('\OCP\IRequest'), diff --git a/apps/files_external/tests/controller/storagescontrollertest.php b/apps/files_external/tests/controller/storagescontrollertest.php index c43761f3bcb..5e1deb821f4 100644 --- a/apps/files_external/tests/controller/storagescontrollertest.php +++ b/apps/files_external/tests/controller/storagescontrollertest.php @@ -75,12 +75,12 @@ abstract class StoragesControllerTest extends \Test\TestCase { $authMech = $this->getAuthMechMock(); $authMech->method('validateStorage') ->willReturn(true); - $authMech->method('isPermitted') + $authMech->method('isVisibleFor') ->willReturn(true); $backend = $this->getBackendMock(); $backend->method('validateStorage') ->willReturn(true); - $backend->method('isPermitted') + $backend->method('isVisibleFor') ->willReturn(true); $storageConfig = new StorageConfig(1); @@ -116,12 +116,12 @@ abstract class StoragesControllerTest extends \Test\TestCase { $authMech = $this->getAuthMechMock(); $authMech->method('validateStorage') ->willReturn(true); - $authMech->method('isPermitted') + $authMech->method('isVisibleFor') ->willReturn(true); $backend = $this->getBackendMock(); $backend->method('validateStorage') ->willReturn(true); - $backend->method('isPermitted') + $backend->method('isVisibleFor') ->willReturn(true); $storageConfig = new StorageConfig(1); @@ -249,12 +249,12 @@ abstract class StoragesControllerTest extends \Test\TestCase { $authMech = $this->getAuthMechMock(); $authMech->method('validateStorage') ->willReturn(true); - $authMech->method('isPermitted') + $authMech->method('isVisibleFor') ->willReturn(true); $backend = $this->getBackendMock(); $backend->method('validateStorage') ->willReturn(true); - $backend->method('isPermitted') + $backend->method('isVisibleFor') ->willReturn(true); $storageConfig = new StorageConfig(255); @@ -338,13 +338,13 @@ abstract class StoragesControllerTest extends \Test\TestCase { $backend = $this->getBackendMock(); $backend->method('validateStorage') ->willReturn($backendValidate); - $backend->method('isPermitted') + $backend->method('isVisibleFor') ->willReturn(true); $authMech = $this->getAuthMechMock(); $authMech->method('validateStorage') ->will($this->returnValue($authMechValidate)); - $authMech->method('isPermitted') + $authMech->method('isVisibleFor') ->willReturn(true); $storageConfig = new StorageConfig(); diff --git a/apps/files_external/tests/controller/userstoragescontrollertest.php b/apps/files_external/tests/controller/userstoragescontrollertest.php index b61174b0797..33ef274c87c 100644 --- a/apps/files_external/tests/controller/userstoragescontrollertest.php +++ b/apps/files_external/tests/controller/userstoragescontrollertest.php @@ -40,6 +40,9 @@ class UserStoragesControllerTest extends StoragesControllerTest { ->disableOriginalConstructor() ->getMock(); + $this->service->method('getVisibilityType') + ->willReturn(BackendService::VISIBILITY_PERSONAL); + $this->controller = new UserStoragesController( 'files_external', $this->getMock('\OCP\IRequest'), @@ -49,21 +52,15 @@ class UserStoragesControllerTest extends StoragesControllerTest { } public function testAddOrUpdateStorageDisallowedBackend() { - $backend1 = $this->getBackendMock(); - $backend1->expects($this->once()) - ->method('isPermitted') - ->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE) - ->willReturn(false); - $backend2 = $this->getBackendMock(); - $backend2->expects($this->once()) - ->method('isPermitted') - ->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_MODIFY) + $backend = $this->getBackendMock(); + $backend->method('isVisibleFor') + ->with(BackendService::VISIBILITY_PERSONAL) ->willReturn(false); $authMech = $this->getAuthMechMock(); $storageConfig = new StorageConfig(1); $storageConfig->setMountPoint('mount'); - $storageConfig->setBackend($backend1); + $storageConfig->setBackend($backend); $storageConfig->setAuthMechanism($authMech); $storageConfig->setBackendOptions([]); @@ -88,8 +85,6 @@ class UserStoragesControllerTest extends StoragesControllerTest { $this->assertEquals(Http::STATUS_UNPROCESSABLE_ENTITY, $response->getStatus()); - $storageConfig->setBackend($backend2); - $response = $this->controller->update( 1, 'mount', diff --git a/apps/files_external/tests/service/backendservicetest.php b/apps/files_external/tests/service/backendservicetest.php index b37b5e9b466..414a9eee2ec 100644 --- a/apps/files_external/tests/service/backendservicetest.php +++ b/apps/files_external/tests/service/backendservicetest.php @@ -83,11 +83,11 @@ class BackendServiceTest extends \Test\TestCase { $backendAllowed = $this->getBackendMock('\User\Mount\Allowed'); $backendAllowed->expects($this->never()) - ->method('removePermission'); + ->method('removeVisibility'); $backendNotAllowed = $this->getBackendMock('\User\Mount\NotAllowed'); $backendNotAllowed->expects($this->once()) - ->method('removePermission') - ->with(BackendService::USER_PERSONAL, BackendService::PERMISSION_CREATE | BackendService::PERMISSION_MOUNT); + ->method('removeVisibility') + ->with(BackendService::VISIBILITY_PERSONAL); $backendAlias = $this->getMockBuilder('\OCA\Files_External\Lib\Backend\Backend') ->disableOriginalConstructor() diff --git a/apps/files_external/tests/service/storagesservicetest.php b/apps/files_external/tests/service/storagesservicetest.php index 28220c9bc2e..ddf52e6272e 100644 --- a/apps/files_external/tests/service/storagesservicetest.php +++ b/apps/files_external/tests/service/storagesservicetest.php @@ -305,6 +305,52 @@ abstract class StoragesServiceTest extends \Test\TestCase { ); } + public function testGetStoragesBackendNotVisible() { + $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB'); + $backend->expects($this->once()) + ->method('isVisibleFor') + ->with($this->service->getVisibilityType()) + ->willReturn(false); + $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism'); + $authMechanism->method('isVisibleFor') + ->with($this->service->getVisibilityType()) + ->willReturn(true); + + $storage = new StorageConfig(255); + $storage->setMountPoint('mountpoint'); + $storage->setBackend($backend); + $storage->setAuthMechanism($authMechanism); + $storage->setBackendOptions(['password' => 'testPassword']); + + $newStorage = $this->service->addStorage($storage); + + $this->assertCount(1, $this->service->getAllStorages()); + $this->assertEmpty($this->service->getStorages()); + } + + public function testGetStoragesAuthMechanismNotVisible() { + $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB'); + $backend->method('isVisibleFor') + ->with($this->service->getVisibilityType()) + ->willReturn(true); + $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism'); + $authMechanism->expects($this->once()) + ->method('isVisibleFor') + ->with($this->service->getVisibilityType()) + ->willReturn(false); + + $storage = new StorageConfig(255); + $storage->setMountPoint('mountpoint'); + $storage->setBackend($backend); + $storage->setAuthMechanism($authMechanism); + $storage->setBackendOptions(['password' => 'testPassword']); + + $newStorage = $this->service->addStorage($storage); + + $this->assertCount(1, $this->service->getAllStorages()); + $this->assertEmpty($this->service->getStorages()); + } + public static function createHookCallback($params) { self::$hookCalls[] = array( 'signal' => Filesystem::signal_create_mount, diff --git a/apps/files_external/tests/service/userglobalstoragesservicetest.php b/apps/files_external/tests/service/userglobalstoragesservicetest.php index 867872f3683..b6dc952605d 100644 --- a/apps/files_external/tests/service/userglobalstoragesservicetest.php +++ b/apps/files_external/tests/service/userglobalstoragesservicetest.php @@ -209,7 +209,11 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest { $expectedPrecedence ) { $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB'); + $backend->method('isVisibleFor') + ->willReturn(true); $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism'); + $authMechanism->method('isVisibleFor') + ->willReturn(true); $storage1 = new StorageConfig(); $storage1->setMountPoint('mountpoint'); @@ -243,6 +247,16 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest { } } + public function testGetStoragesBackendNotVisible() { + // we don't test this here + $this->assertTrue(true); + } + + public function testGetStoragesAuthMechanismNotVisible() { + // we don't test this here + $this->assertTrue(true); + } + public function testHooksAddStorage($a = null, $b = null, $c = null) { // we don't test this here $this->assertTrue(true); diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php index 9e324078dad..734c267020f 100644 --- a/apps/files_sharing/api/sharees.php +++ b/apps/files_sharing/api/sharees.php @@ -62,6 +62,9 @@ class Sharees { /** @var bool */ protected $shareWithGroupOnly = false; + /** @var bool */ + protected $shareeEnumeration = true; + /** @var int */ protected $offset = 0; @@ -134,7 +137,7 @@ class Sharees { } } - if (sizeof($users) < $this->limit) { + if (!$this->shareeEnumeration || sizeof($users) < $this->limit) { $this->reachedEndFor[] = 'users'; } @@ -176,6 +179,10 @@ class Sharees { ]); } } + + if (!$this->shareeEnumeration) { + $this->result['users'] = []; + } } /** @@ -187,7 +194,7 @@ class Sharees { $groups = $this->groupManager->search($search, $this->limit, $this->offset); $groups = array_map(function (IGroup $group) { return $group->getGID(); }, $groups); - if (sizeof($groups) < $this->limit) { + if (!$this->shareeEnumeration || sizeof($groups) < $this->limit) { $this->reachedEndFor[] = 'groups'; } @@ -233,6 +240,10 @@ class Sharees { ]); } } + + if (!$this->shareeEnumeration) { + $this->result['groups'] = []; + } } /** @@ -273,6 +284,10 @@ class Sharees { } } + if (!$this->shareeEnumeration) { + $this->result['remotes'] = []; + } + if (!$foundRemoteById && substr_count($search, '@') >= 1 && substr_count($search, ' ') === 0 && $this->offset === 0) { $this->result['exact']['remotes'][] = [ 'label' => $search, @@ -322,6 +337,7 @@ class Sharees { } $this->shareWithGroupOnly = $this->config->getAppValue('core', 'shareapi_only_share_with_group_members', 'no') === 'yes'; + $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes'; $this->limit = (int) $perPage; $this->offset = $perPage * ($page - 1); diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index 1993efe7d73..4908968a937 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -159,9 +159,18 @@ OCA.Sharing.PublicApp = { }; this.fileList.generatePreviewUrl = function (urlSpec) { + urlSpec = urlSpec || {}; + if (!urlSpec.x) { + urlSpec.x = 36; + } + if (!urlSpec.y) { + urlSpec.y = 36; + } + urlSpec.x *= window.devicePixelRatio; + urlSpec.y *= window.devicePixelRatio; + urlSpec.x = Math.floor(urlSpec.x); + urlSpec.y = Math.floor(urlSpec.y); urlSpec.t = $('#dirToken').val(); - urlSpec.y = Math.floor(36 * window.devicePixelRatio); - urlSpec.x = Math.floor(36 * window.devicePixelRatio); return OC.generateUrl('/apps/files_sharing/ajax/publicpreview.php?') + $.param(urlSpec); }; @@ -293,15 +302,8 @@ $(document).ready(function () { if (window.Files) { // HACK: for oc-dialogs previews that depends on Files: - Files.lazyLoadPreview = function (path, mime, ready, width, height, etag) { - return App.fileList.lazyLoadPreview({ - path: path, - mime: mime, - callback: ready, - width: width, - height: height, - etag: etag - }); + Files.generatePreviewUrl = function (urlSpec) { + return App.fileList.generatePreviewUrl(urlSpec); }; } }); diff --git a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php index 3787ef42d9f..1c29b1da736 100644 --- a/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php +++ b/apps/files_sharing/lib/middleware/sharingcheckmiddleware.php @@ -87,6 +87,11 @@ class SharingCheckMiddleware extends Middleware { return false; } + // Check if the shareAPI is enabled + if ($this->config->getAppValue('core', 'shareapi_enabled', 'yes') !== 'yes') { + return false; + } + // Check whether public sharing is enabled if($this->config->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { return false; diff --git a/apps/files_sharing/lib/mountprovider.php b/apps/files_sharing/lib/mountprovider.php index 14a79625993..458e7f2619b 100644 --- a/apps/files_sharing/lib/mountprovider.php +++ b/apps/files_sharing/lib/mountprovider.php @@ -69,12 +69,11 @@ class MountProvider implements IMountProvider { // for updating etags for the share owner when we make changes to this share. $ownerPropagator = $this->propagationManager->getChangePropagator($share['uid_owner']); - // for updating our etags when changes are made to the share from the owners side (probably indirectly by us trough another share) - $this->propagationManager->listenToOwnerChanges($share['uid_owner'], $user->getUID()); return new SharedMount( '\OC\Files\Storage\Shared', '/' . $user->getUID() . '/' . $share['file_target'], array( + 'propagationManager' => $this->propagationManager, 'propagator' => $ownerPropagator, 'share' => $share, 'user' => $user->getUID() diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 1ac401f3cf8..27dd2f1e485 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -50,13 +50,34 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage { */ private $ownerView; + /** + * @var \OCA\Files_Sharing\Propagation\PropagationManager + */ + private $propagationManager; + + /** + * @var string + */ + private $user; + + private $initialized = false; + public function __construct($arguments) { $this->share = $arguments['share']; $this->ownerView = $arguments['ownerView']; + $this->propagationManager = $arguments['propagationManager']; + $this->user = $arguments['user']; } private function init() { + if ($this->initialized) { + return; + } + $this->initialized = true; Filesystem::initMountPoints($this->share['uid_owner']); + + // for updating our etags when changes are made to the share from the owners side (probably indirectly by us trough another share) + $this->propagationManager->listenToOwnerChanges($this->share['uid_owner'], $this->user); } /** diff --git a/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php index 5c5d5b0d309..91b8b1c7e66 100644 --- a/apps/files_sharing/tests/api/shareestest.php +++ b/apps/files_sharing/tests/api/shareestest.php @@ -110,16 +110,30 @@ class ShareesTest extends TestCase { public function dataGetUsers() { return [ - ['test', false, [], [], [], [], true, false], - ['test', true, [], [], [], [], true, false], + ['test', false, true, [], [], [], [], true, false], + ['test', false, false, [], [], [], [], true, false], + ['test', true, true, [], [], [], [], true, false], + ['test', true, false, [], [], [], [], true, false], [ - 'test', false, [], [], + 'test', false, true, [], [], [ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], ], [], true, $this->getUserMock('test', 'Test') ], [ - 'test', true, [], [], + 'test', false, false, [], [], + [ + ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], + ], [], true, $this->getUserMock('test', 'Test') + ], + [ + 'test', true, true, [], [], + [ + ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], + ], [], true, $this->getUserMock('test', 'Test') + ], + [ + 'test', true, false, [], [], [ ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], ], [], true, $this->getUserMock('test', 'Test') @@ -127,6 +141,7 @@ class ShareesTest extends TestCase { [ 'test', false, + true, [], [ $this->getUserMock('test1', 'Test One'), @@ -141,6 +156,20 @@ class ShareesTest extends TestCase { [ 'test', false, + false, + [], + [ + $this->getUserMock('test1', 'Test One'), + ], + [], + [], + true, + false, + ], + [ + 'test', + false, + true, [], [ $this->getUserMock('test1', 'Test One'), @@ -157,6 +186,21 @@ class ShareesTest extends TestCase { [ 'test', false, + false, + [], + [ + $this->getUserMock('test1', 'Test One'), + $this->getUserMock('test2', 'Test Two'), + ], + [], + [], + true, + false, + ], + [ + 'test', + false, + true, [], [ $this->getUserMock('test0', 'Test'), @@ -175,6 +219,24 @@ class ShareesTest extends TestCase { ], [ 'test', + false, + false, + [], + [ + $this->getUserMock('test0', 'Test'), + $this->getUserMock('test1', 'Test One'), + $this->getUserMock('test2', 'Test Two'), + ], + [ + ['label' => 'Test', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test0']], + ], + [], + true, + false, + ], + [ + 'test', + true, true, ['abc', 'xyz'], [ @@ -191,6 +253,21 @@ class ShareesTest extends TestCase { [ 'test', true, + false, + ['abc', 'xyz'], + [ + ['abc', 'test', 2, 0, ['test1' => 'Test One']], + ['xyz', 'test', 2, 0, []], + ], + [], + [], + true, + false, + ], + [ + 'test', + true, + true, ['abc', 'xyz'], [ ['abc', 'test', 2, 0, [ @@ -213,6 +290,27 @@ class ShareesTest extends TestCase { [ 'test', true, + false, + ['abc', 'xyz'], + [ + ['abc', 'test', 2, 0, [ + 'test1' => 'Test One', + 'test2' => 'Test Two', + ]], + ['xyz', 'test', 2, 0, [ + 'test1' => 'Test One', + 'test2' => 'Test Two', + ]], + ], + [], + [], + true, + false, + ], + [ + 'test', + true, + true, ['abc', 'xyz'], [ ['abc', 'test', 2, 0, [ @@ -231,6 +329,26 @@ class ShareesTest extends TestCase { false, false, ], + [ + 'test', + true, + false, + ['abc', 'xyz'], + [ + ['abc', 'test', 2, 0, [ + 'test' => 'Test One', + ]], + ['xyz', 'test', 2, 0, [ + 'test2' => 'Test Two', + ]], + ], + [ + ['label' => 'Test One', 'value' => ['shareType' => Share::SHARE_TYPE_USER, 'shareWith' => 'test']], + ], + [], + true, + false, + ], ]; } @@ -239,6 +357,7 @@ class ShareesTest extends TestCase { * * @param string $searchTerm * @param bool $shareWithGroupOnly + * @param bool $shareeEnumeration * @param array $groupResponse * @param array $userResponse * @param array $exactExpected @@ -246,10 +365,11 @@ class ShareesTest extends TestCase { * @param bool $reachedEnd * @param mixed $singleUser */ - public function testGetUsers($searchTerm, $shareWithGroupOnly, $groupResponse, $userResponse, $exactExpected, $expected, $reachedEnd, $singleUser) { + public function testGetUsers($searchTerm, $shareWithGroupOnly, $shareeEnumeration, $groupResponse, $userResponse, $exactExpected, $expected, $reachedEnd, $singleUser) { $this->invokePrivate($this->sharees, 'limit', [2]); $this->invokePrivate($this->sharees, 'offset', [0]); $this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]); + $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $user = $this->getUserMock('admin', 'Administrator'); $this->session->expects($this->any()) @@ -290,9 +410,10 @@ class ShareesTest extends TestCase { public function dataGetGroups() { return [ - ['test', false, [], [], [], [], true, false], + ['test', false, true, [], [], [], [], true, false], + ['test', false, false, [], [], [], [], true, false], [ - 'test', false, + 'test', false, true, [$this->getGroupMock('test1')], [], [], @@ -301,7 +422,16 @@ class ShareesTest extends TestCase { false, ], [ - 'test', false, + 'test', false, false, + [$this->getGroupMock('test1')], + [], + [], + [], + true, + false, + ], + [ + 'test', false, true, [ $this->getGroupMock('test'), $this->getGroupMock('test1'), @@ -313,7 +443,19 @@ class ShareesTest extends TestCase { false, ], [ - 'test', false, + 'test', false, false, + [ + $this->getGroupMock('test'), + $this->getGroupMock('test1'), + ], + [], + [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]], + [], + true, + false, + ], + [ + 'test', false, true, [ $this->getGroupMock('test0'), $this->getGroupMock('test1'), @@ -328,7 +470,19 @@ class ShareesTest extends TestCase { null, ], [ - 'test', false, + 'test', false, false, + [ + $this->getGroupMock('test0'), + $this->getGroupMock('test1'), + ], + [], + [], + [], + true, + null, + ], + [ + 'test', false, true, [ $this->getGroupMock('test0'), $this->getGroupMock('test1'), @@ -344,9 +498,24 @@ class ShareesTest extends TestCase { false, $this->getGroupMock('test'), ], - ['test', true, [], [], [], [], true, false], [ - 'test', true, + 'test', false, false, + [ + $this->getGroupMock('test0'), + $this->getGroupMock('test1'), + ], + [], + [ + ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']], + ], + [], + true, + $this->getGroupMock('test'), + ], + ['test', true, true, [], [], [], [], true, false], + ['test', true, false, [], [], [], [], true, false], + [ + 'test', true, true, [ $this->getGroupMock('test1'), $this->getGroupMock('test2'), @@ -358,7 +527,19 @@ class ShareesTest extends TestCase { false, ], [ - 'test', true, + 'test', true, false, + [ + $this->getGroupMock('test1'), + $this->getGroupMock('test2'), + ], + [$this->getGroupMock('test1')], + [], + [], + true, + false, + ], + [ + 'test', true, true, [ $this->getGroupMock('test'), $this->getGroupMock('test1'), @@ -370,7 +551,19 @@ class ShareesTest extends TestCase { false, ], [ - 'test', true, + 'test', true, false, + [ + $this->getGroupMock('test'), + $this->getGroupMock('test1'), + ], + [$this->getGroupMock('test')], + [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]], + [], + true, + false, + ], + [ + 'test', true, true, [ $this->getGroupMock('test'), $this->getGroupMock('test1'), @@ -382,7 +575,19 @@ class ShareesTest extends TestCase { false, ], [ - 'test', true, + 'test', true, false, + [ + $this->getGroupMock('test'), + $this->getGroupMock('test1'), + ], + [$this->getGroupMock('test1')], + [], + [], + true, + false, + ], + [ + 'test', true, true, [ $this->getGroupMock('test'), $this->getGroupMock('test1'), @@ -394,7 +599,19 @@ class ShareesTest extends TestCase { false, ], [ - 'test', true, + 'test', true, false, + [ + $this->getGroupMock('test'), + $this->getGroupMock('test1'), + ], + [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')], + [['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']]], + [], + true, + false, + ], + [ + 'test', true, true, [ $this->getGroupMock('test0'), $this->getGroupMock('test1'), @@ -409,7 +626,19 @@ class ShareesTest extends TestCase { null, ], [ - 'test', true, + 'test', true, false, + [ + $this->getGroupMock('test0'), + $this->getGroupMock('test1'), + ], + [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')], + [], + [], + true, + null, + ], + [ + 'test', true, true, [ $this->getGroupMock('test0'), $this->getGroupMock('test1'), @@ -425,6 +654,20 @@ class ShareesTest extends TestCase { false, $this->getGroupMock('test'), ], + [ + 'test', true, false, + [ + $this->getGroupMock('test0'), + $this->getGroupMock('test1'), + ], + [$this->getGroupMock('test'), $this->getGroupMock('test0'), $this->getGroupMock('test1')], + [ + ['label' => 'test', 'value' => ['shareType' => Share::SHARE_TYPE_GROUP, 'shareWith' => 'test']], + ], + [], + true, + $this->getGroupMock('test'), + ], ]; } @@ -433,6 +676,7 @@ class ShareesTest extends TestCase { * * @param string $searchTerm * @param bool $shareWithGroupOnly + * @param bool $shareeEnumeration * @param array $groupResponse * @param array $userGroupsResponse * @param array $exactExpected @@ -440,10 +684,11 @@ class ShareesTest extends TestCase { * @param bool $reachedEnd * @param mixed $singleGroup */ - public function testGetGroups($searchTerm, $shareWithGroupOnly, $groupResponse, $userGroupsResponse, $exactExpected, $expected, $reachedEnd, $singleGroup) { + public function testGetGroups($searchTerm, $shareWithGroupOnly, $shareeEnumeration, $groupResponse, $userGroupsResponse, $exactExpected, $expected, $reachedEnd, $singleGroup) { $this->invokePrivate($this->sharees, 'limit', [2]); $this->invokePrivate($this->sharees, 'offset', [0]); $this->invokePrivate($this->sharees, 'shareWithGroupOnly', [$shareWithGroupOnly]); + $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $this->groupManager->expects($this->once()) ->method('search') @@ -480,10 +725,22 @@ class ShareesTest extends TestCase { public function dataGetRemote() { return [ - ['test', [], [], [], true], + ['test', [], true, [], [], true], + ['test', [], false, [], [], true], + [ + 'test@remote', + [], + true, + [ + ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], + ], + [], + true, + ], [ 'test@remote', [], + false, [ ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], ], @@ -508,6 +765,7 @@ class ShareesTest extends TestCase { ], ], ], + true, [], [ ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']], @@ -515,6 +773,29 @@ class ShareesTest extends TestCase { true, ], [ + 'test', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + false, + [], + [], + true, + ], + [ 'test@remote', [ [ @@ -532,6 +813,7 @@ class ShareesTest extends TestCase { ], ], ], + true, [ ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], ], @@ -541,6 +823,31 @@ class ShareesTest extends TestCase { true, ], [ + 'test@remote', + [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], + ], + false, + [ + ['label' => 'test@remote', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'test@remote']], + ], + [], + true, + ], + [ 'username@localhost', [ [ @@ -558,11 +865,36 @@ class ShareesTest extends TestCase { ], ], ], + true, [ ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']], ], + [], + true, + ], + [ + 'username@localhost', [ + [ + 'FN' => 'User3 @ Localhost', + ], + [ + 'FN' => 'User2 @ Localhost', + 'CLOUD' => [ + ], + ], + [ + 'FN' => 'User @ Localhost', + 'CLOUD' => [ + 'username@localhost', + ], + ], ], + false, + [ + ['label' => 'User @ Localhost', 'value' => ['shareType' => Share::SHARE_TYPE_REMOTE, 'shareWith' => 'username@localhost']], + ], + [], true, ], ]; @@ -573,11 +905,13 @@ class ShareesTest extends TestCase { * * @param string $searchTerm * @param array $contacts + * @param bool $shareeEnumeration * @param array $exactExpected * @param array $expected * @param bool $reachedEnd */ - public function testGetRemote($searchTerm, $contacts, $exactExpected, $expected, $reachedEnd) { + public function testGetRemote($searchTerm, $contacts, $shareeEnumeration, $exactExpected, $expected, $reachedEnd) { + $this->invokePrivate($this->sharees, 'shareeEnumeration', [$shareeEnumeration]); $this->contactsManager->expects($this->any()) ->method('search') ->with($searchTerm, ['CLOUD', 'FN']) @@ -595,80 +929,84 @@ class ShareesTest extends TestCase { $allTypes = [Share::SHARE_TYPE_USER, Share::SHARE_TYPE_GROUP, Share::SHARE_TYPE_REMOTE]; return [ - [[], '', true, '', null, $allTypes, 1, 200, false], + [[], '', 'yes', true, '', null, $allTypes, 1, 200, false, true], // Test itemType [[ 'search' => '', - ], '', true, '', null, $allTypes, 1, 200, false], + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true], [[ 'search' => 'foobar', - ], '', true, 'foobar', null, $allTypes, 1, 200, false], + ], '', 'yes', true, 'foobar', null, $allTypes, 1, 200, false, true], [[ 'search' => 0, - ], '', true, '0', null, $allTypes, 1, 200, false], + ], '', 'yes', true, '0', null, $allTypes, 1, 200, false, true], // Test itemType [[ 'itemType' => '', - ], '', true, '', '', $allTypes, 1, 200, false], + ], '', 'yes', true, '', '', $allTypes, 1, 200, false, true], [[ 'itemType' => 'folder', - ], '', true, '', 'folder', $allTypes, 1, 200, false], + ], '', 'yes', true, '', 'folder', $allTypes, 1, 200, false, true], [[ 'itemType' => 0, - ], '', true, '', '0', $allTypes, 1, 200, false], + ], '', 'yes', true, '', '0', $allTypes, 1, 200, false, true], // Test shareType [[ - ], '', true, '', null, $allTypes, 1, 200, false], + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true], [[ 'shareType' => 0, - ], '', true, '', null, [0], 1, 200, false], + ], '', 'yes', true, '', null, [0], 1, 200, false, true], [[ 'shareType' => '0', - ], '', true, '', null, [0], 1, 200, false], + ], '', 'yes', true, '', null, [0], 1, 200, false, true], [[ 'shareType' => 1, - ], '', true, '', null, [1], 1, 200, false], + ], '', 'yes', true, '', null, [1], 1, 200, false, true], [[ 'shareType' => 12, - ], '', true, '', null, [], 1, 200, false], + ], '', 'yes', true, '', null, [], 1, 200, false, true], [[ 'shareType' => 'foobar', - ], '', true, '', null, $allTypes, 1, 200, false], + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true], [[ 'shareType' => [0, 1, 2], - ], '', true, '', null, [0, 1], 1, 200, false], + ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true], [[ 'shareType' => [0, 1], - ], '', true, '', null, [0, 1], 1, 200, false], + ], '', 'yes', true, '', null, [0, 1], 1, 200, false, true], [[ 'shareType' => $allTypes, - ], '', true, '', null, $allTypes, 1, 200, false], + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true], [[ 'shareType' => $allTypes, - ], '', false, '', null, [0, 1], 1, 200, false], + ], '', 'yes', false, '', null, [0, 1], 1, 200, false, true], // Test pagination [[ 'page' => 1, - ], '', true, '', null, $allTypes, 1, 200, false], + ], '', 'yes', true, '', null, $allTypes, 1, 200, false, true], [[ 'page' => 10, - ], '', true, '', null, $allTypes, 10, 200, false], + ], '', 'yes', true, '', null, $allTypes, 10, 200, false, true], // Test perPage [[ 'perPage' => 1, - ], '', true, '', null, $allTypes, 1, 1, false], + ], '', 'yes', true, '', null, $allTypes, 1, 1, false, true], [[ 'perPage' => 10, - ], '', true, '', null, $allTypes, 1, 10, false], + ], '', 'yes', true, '', null, $allTypes, 1, 10, false, true], // Test $shareWithGroupOnly setting - [[], 'no', true, '', null, $allTypes, 1, 200, false], - [[], 'yes', true, '', null, $allTypes, 1, 200, true], + [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true], + [[], 'yes', 'yes', true, '', null, $allTypes, 1, 200, true, true], + + // Test $shareeEnumeration setting + [[], 'no', 'yes', true, '', null, $allTypes, 1, 200, false, true], + [[], 'no', 'no', true, '', null, $allTypes, 1, 200, false, false], ]; } @@ -678,6 +1016,7 @@ class ShareesTest extends TestCase { * * @param array $getData * @param string $apiSetting + * @param string $enumSetting * @param bool $remoteSharingEnabled * @param string $search * @param string $itemType @@ -685,18 +1024,22 @@ class ShareesTest extends TestCase { * @param int $page * @param int $perPage * @param bool $shareWithGroupOnly + * @param bool $shareeEnumeration */ - public function testSearch($getData, $apiSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly) { + public function testSearch($getData, $apiSetting, $enumSetting, $remoteSharingEnabled, $search, $itemType, $shareTypes, $page, $perPage, $shareWithGroupOnly, $shareeEnumeration) { $oldGet = $_GET; $_GET = $getData; $config = $this->getMockBuilder('OCP\IConfig') ->disableOriginalConstructor() ->getMock(); - $config->expects($this->once()) + $config->expects($this->exactly(2)) ->method('getAppValue') - ->with('core', 'shareapi_only_share_with_group_members', 'no') - ->willReturn($apiSetting); + ->with('core', $this->anything(), $this->anything()) + ->willReturnMap([ + ['core', 'shareapi_only_share_with_group_members', 'no', $apiSetting], + ['core', 'shareapi_allow_share_dialog_user_enumeration', 'yes', $enumSetting], + ]); $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees') ->setConstructorArgs([ @@ -735,6 +1078,7 @@ class ShareesTest extends TestCase { $this->assertInstanceOf('\OC_OCS_Result', $sharees->search()); $this->assertSame($shareWithGroupOnly, $this->invokePrivate($sharees, 'shareWithGroupOnly')); + $this->assertSame($shareeEnumeration, $this->invokePrivate($sharees, 'shareeEnumeration')); $_GET = $oldGet; } diff --git a/apps/files_sharing/tests/locking.php b/apps/files_sharing/tests/locking.php index 6d13fc1cda5..269c924d142 100644 --- a/apps/files_sharing/tests/locking.php +++ b/apps/files_sharing/tests/locking.php @@ -30,7 +30,7 @@ use OCP\Lock\ILockingProvider; class Locking extends TestCase { /** - * @var \OC_User_Dummy + * @var \Test\Util\User\Dummy */ private $userBackend; @@ -40,7 +40,7 @@ class Locking extends TestCase { public function setUp() { parent::setUp(); - $this->userBackend = new \OC_User_Dummy(); + $this->userBackend = new \Test\Util\User\Dummy(); \OC::$server->getUserManager()->registerBackend($this->userBackend); $this->ownerUid = $this->getUniqueID('owner_'); diff --git a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php index 0db8a1ed5bc..58f4b841339 100644 --- a/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php +++ b/apps/files_sharing/tests/middleware/sharingcheckmiddleware.php @@ -54,7 +54,13 @@ class SharingCheckMiddlewareTest extends \Test\TestCase { ->will($this->returnValue(true)); $this->config - ->expects($this->once()) + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('yes')); + + $this->config + ->expects($this->at(1)) ->method('getAppValue') ->with('core', 'shareapi_allow_links', 'yes') ->will($this->returnValue('yes')); @@ -72,7 +78,7 @@ class SharingCheckMiddlewareTest extends \Test\TestCase { $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); } - public function testIsSharingEnabledWithSharingDisabled() { + public function testIsSharingEnabledWithLinkSharingDisabled() { $this->appManager ->expects($this->once()) ->method('isEnabledForUser') @@ -80,11 +86,34 @@ class SharingCheckMiddlewareTest extends \Test\TestCase { ->will($this->returnValue(true)); $this->config - ->expects($this->once()) + ->expects($this->at(0)) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('yes')); + + $this->config + ->expects($this->at(1)) ->method('getAppValue') ->with('core', 'shareapi_allow_links', 'yes') ->will($this->returnValue('no')); $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); } + + public function testIsSharingEnabledWithSharingAPIDisabled() { + $this->appManager + ->expects($this->once()) + ->method('isEnabledForUser') + ->with('files_sharing') + ->will($this->returnValue(true)); + + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('core', 'shareapi_enabled', 'yes') + ->will($this->returnValue('no')); + + $this->assertFalse(self::invokePrivate($this->sharingCheckMiddleware, 'isSharingEnabled')); + } + } diff --git a/apps/files_sharing/tests/testcase.php b/apps/files_sharing/tests/testcase.php index 7533b13f79d..c91734a5b03 100644 --- a/apps/files_sharing/tests/testcase.php +++ b/apps/files_sharing/tests/testcase.php @@ -72,7 +72,7 @@ abstract class TestCase extends \Test\TestCase { \OC::registerShareHooks(); // create users - $backend = new \OC_User_Dummy(); + $backend = new \Test\Util\User\Dummy(); \OC_User::useBackend($backend); $backend->createUser(self::TEST_FILES_SHARING_API_USER1, self::TEST_FILES_SHARING_API_USER1); $backend->createUser(self::TEST_FILES_SHARING_API_USER2, self::TEST_FILES_SHARING_API_USER2); diff --git a/apps/files_trashbin/js/app.js b/apps/files_trashbin/js/app.js index 473cce88a71..c3be762f095 100644 --- a/apps/files_trashbin/js/app.js +++ b/apps/files_trashbin/js/app.js @@ -59,6 +59,7 @@ OCA.Trashbin.App = { fileActions.registerAction({ name: 'Delete', + displayName: t('files', 'Delete'), mime: 'all', permissions: OC.PERMISSION_READ, icon: function() { diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 3b2d4cf5929..2a9df94988d 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -895,7 +895,7 @@ class Trashbin { $view = new \OC\Files\View('/' . $user . '/files_trashbin'); if ($view->is_dir('/files') && $dh = $view->opendir('/files')) { while ($file = readdir($dh)) { - if ($file !== '.' and $file !== '..') { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { return false; } } diff --git a/apps/files_versions/lib/storage.php b/apps/files_versions/lib/storage.php index 6aa58c55e9b..bdf1811c5f9 100644 --- a/apps/files_versions/lib/storage.php +++ b/apps/files_versions/lib/storage.php @@ -315,6 +315,9 @@ class Storage { if (self::copyFileContents($users_view, 'files_versions' . $filename . '.v' . $revision, 'files' . $filename)) { $files_view->touch($file, $revision); Storage::scheduleExpire($uid, $file); + \OC_Hook::emit('\OCP\Versions', 'rollback', array( + 'path' => $filename, + )); return true; } else if ($versionCreated) { self::deleteVersion($users_view, $version); diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php index 7cca409ed6c..d4a85c8bffe 100644 --- a/apps/files_versions/tests/versions.php +++ b/apps/files_versions/tests/versions.php @@ -580,6 +580,35 @@ class Test_Files_Versioning extends \Test\TestCase { $this->doTestRestore(); } + /** + * @param string $hookName name of hook called + * @param string $params variable to recieve parameters provided by hook + */ + private function connectMockHooks($hookName, &$params) { + if ($hookName === null) { + return; + } + + $eventHandler = $this->getMockBuilder('\stdclass') + ->setMethods(['callback']) + ->getMock(); + + $eventHandler->expects($this->any()) + ->method('callback') + ->will($this->returnCallback( + function($p) use (&$params) { + $params = $p; + } + )); + + \OCP\Util::connectHook( + '\OCP\Versions', + $hookName, + $eventHandler, + 'callback' + ); + } + private function doTestRestore() { $filePath = self::TEST_VERSIONS_USER . '/files/sub/test.txt'; $this->rootView->file_put_contents($filePath, 'test file'); @@ -608,7 +637,15 @@ class Test_Files_Versioning extends \Test\TestCase { $this->assertEquals('test file', $this->rootView->file_get_contents($filePath)); $info1 = $this->rootView->getFileInfo($filePath); + $params = array(); + $this->connectMockHooks('rollback', $params); + \OCA\Files_Versions\Storage::rollback('sub/test.txt', $t2); + $expectedParams = array( + 'path' => '/sub/test.txt', + ); + + $this->assertEquals($expectedParams, $params); $this->assertEquals('version2', $this->rootView->file_get_contents($filePath)); $info2 = $this->rootView->getFileInfo($filePath); @@ -749,7 +786,7 @@ class Test_Files_Versioning extends \Test\TestCase { public static function loginHelper($user, $create = false) { if ($create) { - $backend = new \OC_User_Dummy(); + $backend = new \Test\Util\User\Dummy(); $backend->createUser($user, $user); \OC::$server->getUserManager()->registerBackend($backend); } diff --git a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js index b73d267d168..0316db5b61c 100644 --- a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js +++ b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js @@ -71,7 +71,8 @@ OCA = OCA || {}; ], 'ldap_login_filter_mode' ); - _.bindAll(this, 'onVerifyClick'); + _.bindAll(this, 'onVerifyClick', 'onTestLoginnameChange'); + this.managedItems.ldap_test_loginname.$element.keyup(this.onTestLoginnameChange); this.managedItems.ldap_test_loginname.$relatedElements.click(this.onVerifyClick); }, @@ -231,6 +232,16 @@ OCA = OCA || {}; } else { this.configModel.requestWizard('ldap_test_loginname', {ldap_test_loginname: testLogin}); } + }, + + /** + * enables/disables the "Verify Settings" button, depending whether + * the corresponding text input has a value or not + */ + onTestLoginnameChange: function() { + var loginName = this.managedItems.ldap_test_loginname.$element.val(); + var beDisabled = !_.isString(loginName) || !loginName.trim(); + this.managedItems.ldap_test_loginname.$relatedElements.prop('disabled', beDisabled); } }); diff --git a/apps/user_ldap/templates/part.wizard-loginfilter.php b/apps/user_ldap/templates/part.wizard-loginfilter.php index 8d9fccf24b8..a13931d9327 100644 --- a/apps/user_ldap/templates/part.wizard-loginfilter.php +++ b/apps/user_ldap/templates/part.wizard-loginfilter.php @@ -52,7 +52,7 @@ placeholder="<?php p($l->t('Test Loginname'));?>" class="ldapVerifyInput" title="Attempts to receive a DN for the given loginname and the current login filter"/> - <button class="ldapVerifyLoginName" name="ldapTestLoginSettings" type="button"> + <button class="ldapVerifyLoginName" name="ldapTestLoginSettings" type="button" disabled="disabled"> <?php p($l->t('Verify settings'));?> </button> </p> diff --git a/autotest.sh b/autotest.sh index 243b8df0c6a..cd36193cf6c 100755 --- a/autotest.sh +++ b/autotest.sh @@ -203,8 +203,14 @@ function execute_tests { echo "Waiting for Oracle initialization ... " - # grep exits on the first match and then the script continues - times out after 2 minutes - timeout 240 docker logs -f "$DOCKER_CONTAINER_ID" 2>&1 | grep -q "Grant succeeded." + # Try to connect to the OCI host via sqlplus to ensure that the connection is already running + for i in {1..48} + do + if sqlplus "system/oracle@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=$DATABASEHOST)(Port=1521))(CONNECT_DATA=(SID=XE)))" < /dev/null | grep 'Connected to'; then + break; + fi + sleep 5 + done DATABASEUSER=autotest DATABASENAME='XE' diff --git a/config/config.sample.php b/config/config.sample.php index 8949bd44465..51529cdb0cc 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -609,7 +609,9 @@ $CONFIG = array( /** * ownCloud uses some 3rd party PHP components to provide certain functionality. * These components are shipped as part of the software package and reside in - * ``owncloud/3rdparty``. Use this option to configure a different location. + * ``owncloud/3rdparty``. Use this option to configure a different location. + * For example, if your location is /var/www/owncloud/foo/3rdparty, then the + * correct configuration is '3rdpartyroot' => '/var/www/owncloud/foo/', */ '3rdpartyroot' => '', diff --git a/core/ajax/share.php b/core/ajax/share.php index 253095f2980..50c99cb56b4 100644 --- a/core/ajax/share.php +++ b/core/ajax/share.php @@ -410,6 +410,16 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo } } + $sharingAutocompletion = \OC::$server->getConfig() + ->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'); + + if ($sharingAutocompletion !== 'yes') { + $searchTerm = strtolower($_GET['search']); + $shareWith = array_filter($shareWith, function($user) use ($searchTerm) { + return strtolower($user['label']) === $searchTerm + || strtolower($user['value']['shareWith']) === $searchTerm; + }); + } $sorter = new \OC\Share\SearchResultSorter((string)$_GET['search'], 'label', diff --git a/core/command/app/checkcode.php b/core/command/app/checkcode.php index a4e7322460f..9f6e0729ce9 100644 --- a/core/command/app/checkcode.php +++ b/core/command/app/checkcode.php @@ -26,6 +26,8 @@ namespace OC\Core\Command\App; use OC\App\CodeChecker\CodeChecker; use OC\App\CodeChecker\EmptyCheck; +use OC\App\CodeChecker\InfoChecker; +use OC\App\InfoParser; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -33,12 +35,21 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class CheckCode extends Command { + + /** @var InfoParser */ + private $infoParser; + protected $checkers = [ 'private' => '\OC\App\CodeChecker\PrivateCheck', 'deprecation' => '\OC\App\CodeChecker\DeprecationCheck', 'strong-comparison' => '\OC\App\CodeChecker\StrongComparisonCheck', ]; + public function __construct(InfoParser $infoParser) { + parent::__construct(); + $this->infoParser = $infoParser; + } + protected function configure() { $this ->setName('app:check-code') @@ -54,6 +65,12 @@ class CheckCode extends Command { InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'enable the specified checker(s)', [ 'private', 'deprecation', 'strong-comparison' ] + ) + ->addOption( + '--skip-validate-info', + null, + InputOption::VALUE_NONE, + 'skips the info.xml/version check' ); } @@ -84,7 +101,7 @@ class CheckCode extends Command { $output->writeln("<info>Analysing {$filename}</info>"); } - // show error count if there are errros present or the verbosity is high + // show error count if there are errors present or the verbosity is high if($count > 0 || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $output->writeln(" {$count} errors"); } @@ -98,6 +115,53 @@ class CheckCode extends Command { } }); $errors = $codeChecker->analyse($appId); + + if(!$input->getOption('skip-validate-info')) { + $infoChecker = new InfoChecker($this->infoParser); + + $infoChecker->listen('InfoChecker', 'mandatoryFieldMissing', function($key) use ($output) { + $output->writeln("<error>Mandatory field missing: $key</error>"); + }); + + $infoChecker->listen('InfoChecker', 'deprecatedFieldFound', function($key, $value) use ($output) { + if($value === [] || is_null($value) || $value === '') { + $output->writeln("<info>Deprecated field available: $key</info>"); + } else { + $output->writeln("<info>Deprecated field available: $key => $value</info>"); + } + }); + + $infoChecker->listen('InfoChecker', 'differentVersions', function($versionFile, $infoXML) use ($output) { + $output->writeln("<error>Different versions provided (appinfo/version: $versionFile - appinfo/info.xml: $infoXML)</error>"); + }); + + $infoChecker->listen('InfoChecker', 'sameVersions', function($path) use ($output) { + $output->writeln("<info>Version file isn't needed anymore and can be safely removed ($path)</info>"); + }); + + $infoChecker->listen('InfoChecker', 'migrateVersion', function($version) use ($output) { + $output->writeln("<info>Migrate the app version to appinfo/info.xml (add <version>$version</version> to appinfo/info.xml and remove appinfo/version)</info>"); + }); + + if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $infoChecker->listen('InfoChecker', 'mandatoryFieldFound', function($key, $value) use ($output) { + $output->writeln("<info>Mandatory field available: $key => $value</info>"); + }); + + $infoChecker->listen('InfoChecker', 'optionalFieldFound', function($key, $value) use ($output) { + $output->writeln("<info>Optional field available: $key => $value</info>"); + }); + + $infoChecker->listen('InfoChecker', 'unusedFieldFound', function($key, $value) use ($output) { + $output->writeln("<info>Unused field available: $key => $value</info>"); + }); + } + + $infoErrors = $infoChecker->analyse($appId); + + $errors = array_merge($errors, $infoErrors); + } + if (empty($errors)) { $output->writeln('<info>App is compliant - awesome job!</info>'); return 0; diff --git a/core/css/apps.css b/core/css/apps.css index 6dd7e63bb69..23e0c519d00 100644 --- a/core/css/apps.css +++ b/core/css/apps.css @@ -417,7 +417,6 @@ position: relative; height: 100%; overflow-y: auto; - -webkit-overflow-scrolling: touch; } #app-content-wrapper { diff --git a/core/css/multiselect.css b/core/css/multiselect.css index a9451964f59..a4b03319156 100644 --- a/core/css/multiselect.css +++ b/core/css/multiselect.css @@ -33,9 +33,8 @@ ul.multiselectoptions>li { white-space: nowrap; } -ul.multiselectoptions > li > input[type="checkbox"] { - margin: 10px 7px; - vertical-align: middle; +ul.multiselectoptions > li > input[type="checkbox"]+label:before { + margin-left: 7px; } ul.multiselectoptions > li input[type='checkbox']+label { font-weight: normal; diff --git a/core/css/styles.css b/core/css/styles.css index 1a4a4ab4f3d..d952a33c24a 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -158,7 +158,9 @@ textarea:hover, textarea:focus, textarea:active { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; opacity: 1; } -input[type="checkbox"] { + +/* ie8 doesn't support :checked */ +html:not(.ie8) input[type="checkbox"].checkbox { margin:0; padding:0; height:auto; @@ -166,7 +168,7 @@ input[type="checkbox"] { display: none; } -input[type="checkbox"] + label:before { +html:not(.ie8) input[type="checkbox"].checkbox + label:before { content: ""; display: inline-block; @@ -174,25 +176,27 @@ input[type="checkbox"] + label:before { width: 20px; vertical-align: middle; - background: url('../img/actions/checkbox.svg') left center no-repeat; + background: url('../img/actions/checkbox.svg') left top no-repeat; opacity: 0.7; } -input[type="checkbox"].u-left +label:before { float: left; } +html:not(.ie8) input[type="checkbox"].checkbox:disabled +label:before { opacity: .6; } + +html:not(.ie8) input[type="checkbox"].checkbox.u-left +label:before { float: left; } -input[type="checkbox"].white + label:before { +html:not(.ie8) input[type="checkbox"].checkbox--white + label:before { background-image: url('../img/actions/checkbox-white.svg'); } -input[type="checkbox"]:checked + label:before { +html:not(.ie8) input[type="checkbox"].checkbox:checked + label:before { background-image: url('../img/actions/checkbox-checked.svg'); } -input[type="checkbox"].white:checked + label:before { +html:not(.ie8) input[type="checkbox"].checkbox--white:checked + label:before { background-image: url('../img/actions/checkbox-checked-white.svg'); } -input[type="checkbox"]:hover+label:before, input[type="checkbox"]:focus+label:before { +html:not(.ie8) input[type="checkbox"].checkbox:hover+label:before, input[type="checkbox"]:focus+label:before { color:#111 !important; } diff --git a/core/img/actions/close.png b/core/img/actions/close.png Binary files differindex ece33258e56..66e3c26cc65 100644 --- a/core/img/actions/close.png +++ b/core/img/actions/close.png diff --git a/core/img/actions/close.svg b/core/img/actions/close.svg index 4471dbc6301..e060da3f8bb 100644 --- a/core/img/actions/close.svg +++ b/core/img/actions/close.svg @@ -1,3 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/"> - <path d="M12.95,11.536,11.536,12.95,8,9.4142,4.4645,12.95,3.0503,11.536,6.5858,8,3.0503,4.4644,4.4645,3.0502,8,6.5858,11.516,3.0311,12.95,4.4644,9.4143,8z" fill="#000"/> + <defs> + <filter id="a" style="color-interpolation-filters:sRGB" height="1.5994" width="1.6006" y="-.29971" x="-.30029"> + <feGaussianBlur stdDeviation="1.2386625"/> + </filter> + </defs> + <path d="m12.95 11.536-1.414 1.414-3.536-3.5358-3.5355 3.5358-1.4142-1.414 3.5355-3.536-3.5355-3.5356 1.4142-1.4142 3.5355 3.5356 3.516-3.5547 1.434 1.4333-3.5357 3.5356z" filter="url(#a)" stroke="#fff" stroke-width="2" fill="#fff"/> + <path d="m12.95 11.536-1.414 1.414-3.536-3.5358-3.5355 3.5358-1.4142-1.414 3.5355-3.536-3.5355-3.5356 1.4142-1.4142 3.5355 3.5356 3.516-3.5547 1.434 1.4333-3.5357 3.5356z"/> </svg> diff --git a/core/js/js.js b/core/js/js.js index de773dc1221..b5971bfc579 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -1972,4 +1972,5 @@ jQuery.fn.tipsy = function(argument) { this.tooltip(argument); jQuery.fn.tooltip.call(this, argument); } + return this; } diff --git a/core/js/mimetypelist.js b/core/js/mimetypelist.js index e49ace6df73..af2ad73c51b 100644 --- a/core/js/mimetypelist.js +++ b/core/js/mimetypelist.js @@ -9,26 +9,23 @@ OC.MimeTypeList={ aliases: { "application/coreldraw": "image", - "application/epub+zip": "text", - "application/font-sfnt": "image", - "application/font-woff": "image", - "application/illustrator": "image", - "application/javascript": "text/code", + "application/font-sfnt": "font", + "application/font-woff": "font", + "application/illustrator": "image/vector", "application/json": "text/code", - "application/msaccess": "file", + "application/msaccess": "database", "application/msexcel": "x-office/spreadsheet", "application/mspowerpoint": "x-office/presentation", "application/msword": "x-office/document", "application/octet-stream": "file", - "application/postscript": "image", - "application/rss+xml": "text/code", + "application/postscript": "image/vector", "application/vnd.android.package-archive": "package/x-generic", "application/vnd.ms-excel": "x-office/spreadsheet", "application/vnd.ms-excel.addin.macroEnabled.12": "x-office/spreadsheet", "application/vnd.ms-excel.sheet.binary.macroEnabled.12": "x-office/spreadsheet", "application/vnd.ms-excel.sheet.macroEnabled.12": "x-office/spreadsheet", "application/vnd.ms-excel.template.macroEnabled.12": "x-office/spreadsheet", - "application/vnd.ms-fontobject": "image", + "application/vnd.ms-fontobject": "font", "application/vnd.ms-powerpoint": "x-office/presentation", "application/vnd.ms-powerpoint.addin.macroEnabled.12": "x-office/presentation", "application/vnd.ms-powerpoint.presentation.macroEnabled.12": "x-office/presentation", @@ -52,56 +49,48 @@ OC.MimeTypeList={ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "x-office/document", "application/vnd.openxmlformats-officedocument.wordprocessingml.template": "x-office/document", "application/x-7z-compressed": "package/x-generic", - "application/x-cbr": "text", "application/x-compressed": "package/x-generic", "application/x-dcraw": "image", "application/x-deb": "package/x-generic", - "application/x-font": "image", + "application/x-font": "font", "application/x-gimp": "image", "application/x-gzip": "package/x-generic", "application/x-perl": "text/code", "application/x-photoshop": "image", "application/x-php": "text/code", "application/x-rar-compressed": "package/x-generic", - "application/x-shockwave-flash": "application", "application/x-tar": "package/x-generic", "application/x-tex": "text", "application/xml": "text/html", "application/yaml": "text/code", "application/zip": "package/x-generic", - "database": "file", "httpd/unix-directory": "dir", - "image/svg+xml": "image", - "image/vector": "image", + "image/svg+xml": "image/vector", "text/css": "text/code", "text/csv": "x-office/spreadsheet", - "text/html": "text/code", - "text/x-c": "text/code", - "text/x-h": "text/code", - "text/x-python": "text/code", - "text/x-shellscript": "text/code", - "web": "text/code" + "text/x-shellscript": "text/code" }, files: [ - "video", + "application-pdf", + "application", + "audio", + "file", "folder-drag-accept", + "folder-external", "folder-public", + "folder-shared", + "folder-starred", + "folder", + "image", "package-x-generic", - "folder-external", - "text-vcard", - "application", + "text-calendar", "text-code", - "x-office-spreadsheet", - "application-pdf", - "folder", + "text-vcard", + "text", + "video", "x-office-document", - "text-calendar", "x-office-presentation", - "file", - "text", - "folder-shared", - "image", - "audio" + "x-office-spreadsheet" ], themes: [] }; diff --git a/core/js/multiselect.js b/core/js/multiselect.js index 41dc68ac051..6d5c54ac0f5 100644 --- a/core/js/multiselect.js +++ b/core/js/multiselect.js @@ -109,6 +109,9 @@ var id='ms'+multiSelectId+'-option-'+item; var input=$('<input type="' + inputType + '"/>'); input.attr('id',id); + if(inputType === 'checkbox') { + input.addClass('checkbox'); + } if(settings.singleSelect) { input.attr('name', 'ms'+multiSelectId+'-option'); } diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index 719ac8587a4..38b91be9d2e 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -388,9 +388,9 @@ var OCdialogs = { c: original.etag, forceIcon: 0 }; - var previewpath = OC.generateUrl('/core/preview.png?') + $.param(urlSpec); + var previewpath = Files.generatePreviewUrl(urlSpec); // Escaping single quotes - previewpath = previewpath.replace(/'/g, "%27") + previewpath = previewpath.replace(/'/g, "%27"); $originalDiv.find('.icon').css({"background-image": "url('" + previewpath + "')"}); getCroppedPreview(replacement).then( function(path){ diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js index 2b61dab3ceb..57743118f28 100644 --- a/core/js/sharedialogview.js +++ b/core/js/sharedialogview.js @@ -176,6 +176,9 @@ $shareField.autocomplete({ minLength: 2, delay: 750, + focus: function(event) { + event.preventDefault(); + }, source: this.autocompleteHandler, select: this._onSelectRecipient }).data('ui-autocomplete')._renderItem = this.autocompleteRenderItem; diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js index ff0d3a6d800..13396670aae 100644 --- a/core/js/shareitemmodel.js +++ b/core/js/shareitemmodel.js @@ -50,7 +50,7 @@ * @property {string} token * @property {string} share_with * @property {string} share_with_displayname - * @property {string} share_mail_send + * @property {string} mail_send * @property {OC.Share.Types.Collection|undefined} collection * @property {Date} expiration optional? * @property {number} stime optional? @@ -64,6 +64,15 @@ */ /** + * These properties are sometimes returned by the server as strings instead + * of integers, so we need to convert them accordingly... + */ + var SHARE_RESPONSE_INT_PROPS = [ + 'id', 'file_parent', 'mail_send', 'file_source', 'item_source', 'permissions', + 'storage', 'share_type', 'parent', 'stime' + ]; + + /** * @class OCA.Share.ShareItemModel * @classdesc * @@ -288,8 +297,7 @@ * @returns {boolean} */ hasUserShares: function() { - var shares = this.get('shares'); - return _.isArray(shares) && shares.length > 0; + return this.getSharesWithCurrentItem().length > 0; }, /** @@ -399,6 +407,20 @@ }, /** + * Returns all share entries that only apply to the current item + * (file/folder) + * + * @return {Array.<OC.Share.Types.ShareInfo>} + */ + getSharesWithCurrentItem: function() { + var shares = this.get('shares') || []; + var fileId = this.fileInfoModel.get('id'); + return _.filter(shares, function(share) { + return share.item_source === fileId; + }); + }, + + /** * @param shareIndex * @returns {string} */ @@ -462,7 +484,7 @@ if(!_.isObject(share)) { throw "Unknown Share"; } - return share.share_mail_send === '1'; + return share.mail_send === 1; }, /** @@ -618,6 +640,8 @@ var fileId = this.fileInfoModel.get('id'); if (!shares || !shares.length) { delete OC.Share.statuses[fileId]; + OC.Share.currentShares = {}; + OC.Share.itemShares = []; return; } @@ -671,7 +695,19 @@ } /** @type {OC.Share.Types.ShareInfo[]} **/ - var shares = _.toArray(data.shares); + var shares = _.map(data.shares, function(share) { + // properly parse some values because sometimes the server + // returns integers as string... + var i; + for (i = 0; i < SHARE_RESPONSE_INT_PROPS.length; i++) { + var prop = SHARE_RESPONSE_INT_PROPS[i]; + if (!_.isUndefined(share[prop])) { + share[prop] = parseInt(share[prop], 10); + } + } + return share; + }); + this._legacyFillCurrentShares(shares); var linkShare = { isLinkShare: false }; diff --git a/core/js/tests/specs/shareitemmodelSpec.js b/core/js/tests/specs/shareitemmodelSpec.js index c1d820052e2..b4403e28475 100644 --- a/core/js/tests/specs/shareitemmodelSpec.js +++ b/core/js/tests/specs/shareitemmodelSpec.js @@ -169,7 +169,7 @@ describe('OC.Share.ShareItemModel', function() { /* jshint camelcase: false */ shares: [{ displayname_owner: 'root', - expiration: 1111, + expiration: '2015-10-12 00:00:00', file_source: 123, file_target: '/folder', id: 20, @@ -187,7 +187,7 @@ describe('OC.Share.ShareItemModel', function() { uid_owner: 'root' }, { displayname_owner: 'root', - expiration: 2222, + expiration: '2015-10-15 00:00:00', file_source: 456, file_target: '/file_in_folder.txt', id: 21, @@ -249,10 +249,7 @@ describe('OC.Share.ShareItemModel', function() { it('allows owner to share their own share when they are also the recipient', function() { OC.currentUser = 'user1'; loadItemStub.yields({ - reshare: { - permissions: OC.PERMISSION_READ, - uid_owner: 'user1' - }, + reshare: {}, shares: [] }); @@ -261,6 +258,108 @@ describe('OC.Share.ShareItemModel', function() { // sharing still allowed expect(model.get('permissions') & OC.PERMISSION_SHARE).toEqual(OC.PERMISSION_SHARE); }); + it('properly parses integer values when the server is in the mood of returning ints as string', function() { + loadItemStub.yields({ + reshare: {}, + shares: [{ + displayname_owner: 'root', + expiration: '2015-10-12 00:00:00', + file_source: '123', + file_target: '/folder', + id: '20', + item_source: '123', + item_type: 'file', + mail_send: '0', + parent: '999', + path: '/folder', + permissions: '' + OC.PERMISSION_READ, + share_type: '' + OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + stime: '1403884258', + storage: '1', + token: 'tehtoken', + uid_owner: 'root' + }] + }); + + model.fetch(); + + var shares = model.get('shares'); + expect(shares.length).toEqual(1); + + var share = shares[0]; + expect(share.id).toEqual(20); + expect(share.file_source).toEqual(123); + expect(share.file_target).toEqual('/folder'); + expect(share.item_source).toEqual(123); + expect(share.item_type).toEqual('file'); + expect(share.displayname_owner).toEqual('root'); + expect(share.mail_send).toEqual(0); + expect(share.parent).toEqual(999); + expect(share.path).toEqual('/folder'); + expect(share.permissions).toEqual(OC.PERMISSION_READ); + expect(share.share_type).toEqual(OC.Share.SHARE_TYPE_USER); + expect(share.share_with).toEqual('user1'); + expect(share.stime).toEqual(1403884258); + expect(share.expiration).toEqual('2015-10-12 00:00:00'); + }); + }); + describe('hasUserShares', function() { + it('returns false when no user shares exist', function() { + loadItemStub.yields({ + reshare: {}, + shares: [] + }); + + model.fetch(); + + expect(model.hasUserShares()).toEqual(false); + }); + it('returns true when user shares exist on the current item', function() { + loadItemStub.yields({ + reshare: {}, + shares: [{ + id: 1, + share_type: OC.Share.SHARE_TYPE_USER, + share_with: 'user1', + item_source: '123' + }] + }); + + model.fetch(); + + expect(model.hasUserShares()).toEqual(true); + }); + it('returns true when group shares exist on the current item', function() { + loadItemStub.yields({ + reshare: {}, + shares: [{ + id: 1, + share_type: OC.Share.SHARE_TYPE_GROUP, + share_with: 'group1', + item_source: '123' + }] + }); + + model.fetch(); + + expect(model.hasUserShares()).toEqual(true); + }); + it('returns false when share exist on parent item', function() { + loadItemStub.yields({ + reshare: {}, + shares: [{ + id: 1, + share_type: OC.Share.SHARE_TYPE_GROUP, + share_with: 'group1', + item_source: '111' + }] + }); + + model.fetch(); + + expect(model.hasUserShares()).toEqual(false); + }); }); describe('Util', function() { diff --git a/core/register_command.php b/core/register_command.php index 114e115c491..878542f72c9 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -28,7 +28,8 @@ /** @var $application Symfony\Component\Console\Application */ $application->add(new OC\Core\Command\Status); $application->add(new OC\Core\Command\Check(\OC::$server->getConfig())); -$application->add(new OC\Core\Command\App\CheckCode()); +$infoParser = new \OC\App\InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator()); +$application->add(new OC\Core\Command\App\CheckCode($infoParser)); $application->add(new OC\Core\Command\L10n\CreateJs()); if (\OC::$server->getConfig()->getSystemValue('installed', false)) { diff --git a/core/search/js/search.js b/core/search/js/search.js index bc67eb0e154..4e83a070170 100644 --- a/core/search/js/search.js +++ b/core/search/js/search.js @@ -217,10 +217,10 @@ $status.addClass('emptycontent').removeClass('status'); $status.html(''); $status.append('<div class="icon-search"></div>'); - $status.append('<h2>' + t('core', 'No search results in other places') + '</h2>'); + $status.append('<h2>' + t('core', 'No search results in other folders') + '</h2>'); } else { $status.removeClass('emptycontent').addClass('status'); - $status.text(n('core', '{count} search result in other places', '{count} search results in other places', count, {count:count})); + $status.text(n('core', '{count} search result in another folder', '{count} search results in other folders', count, {count:count})); } } function renderCurrent() { diff --git a/core/shipped.json b/core/shipped.json index 7993b61569c..ffa4ee9c738 100644 --- a/core/shipped.json +++ b/core/shipped.json @@ -3,11 +3,11 @@ "shippedApps": [ "activity", "admin_audit", + "encryption", "enterprise_key", "external", "files", "files_antivirus", - "encryption", "files_external", "files_ldap_home", "files_locking", @@ -21,6 +21,7 @@ "firewall", "firstrunwizard", "gallery", + "notifications", "objectstore", "provisioning_api", "sharepoint", @@ -29,7 +30,6 @@ "user_external", "user_ldap", "user_shibboleth", - "user_webdavauth", "windows_network_drive" ] } diff --git a/core/templates/login.php b/core/templates/login.php index 2057b1034d0..db77f63bbd0 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -65,7 +65,7 @@ script('core', [ <?php endif; ?> <?php if ($_['rememberLoginAllowed'] === true) : ?> <div class="remember-login-container"> - <input type="checkbox" name="remember_login" value="1" id="remember_login" class="white"> + <input type="checkbox" name="remember_login" value="1" id="remember_login" class="checkbox checkbox--white"> <label for="remember_login"><?php p($l->t('remember')); ?></label> </div> <?php endif; ?> diff --git a/lib/base.php b/lib/base.php index 3624a3fbaf9..f99acaaa80a 100644 --- a/lib/base.php +++ b/lib/base.php @@ -803,8 +803,9 @@ class OC { OC_Hook::connect('\OCP\Versions', 'preDelete', 'OC\Preview', 'prepare_delete'); OC_Hook::connect('\OCP\Trashbin', 'preDelete', 'OC\Preview', 'prepare_delete'); OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC\Preview', 'post_delete_files'); - OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete'); + OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete_versions'); OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete'); + OC_Hook::connect('\OCP\Versions', 'rollback', 'OC\Preview', 'post_delete_versions'); } /** diff --git a/lib/private/app.php b/lib/private/app.php index 6c9f7615228..5122a4964d4 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -411,7 +411,7 @@ class OC_App { /** * Returns the Settings Navigation * - * @return string + * @return string[] * * This function returns an array containing all settings pages added. The * entries are sorted by the key 'order' ascending. @@ -837,7 +837,7 @@ class OC_App { $info['active'] = $active; - if (isset($info['shipped']) and ($info['shipped'] == 'true')) { + if (self::isShipped($app)) { $info['internal'] = true; $info['level'] = self::officialApp; $info['removable'] = false; diff --git a/lib/private/app/codechecker/infochecker.php b/lib/private/app/codechecker/infochecker.php new file mode 100644 index 00000000000..91580bde07d --- /dev/null +++ b/lib/private/app/codechecker/infochecker.php @@ -0,0 +1,146 @@ +<?php +/** + * @author Morris Jobke <hey@morrisjobke.de> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\App\CodeChecker; + +use OC\App\InfoParser; +use OC\Hooks\BasicEmitter; + +class InfoChecker extends BasicEmitter { + + /** @var InfoParser */ + private $infoParser; + + private $mandatoryFields = [ + 'author', + 'description', + 'id', + 'licence', + 'name', + ]; + private $optionalFields = [ + 'bugs', + 'category', + 'default_enable', + 'dependencies', + 'documentation', + 'namespace', + 'ocsid', + 'public', + 'remote', + 'repository', + 'require', + 'requiremin', + 'types', + 'version', + 'website', + ]; + private $deprecatedFields = [ + 'info', + 'shipped', + 'standalone', + ]; + + public function __construct(InfoParser $infoParser) { + $this->infoParser = $infoParser; + } + + /** + * @param string $appId + * @return array + */ + public function analyse($appId) { + $appPath = \OC_App::getAppPath($appId); + if ($appPath === false) { + throw new \RuntimeException("No app with given id <$appId> known."); + } + + $errors = []; + + $info = $this->infoParser->parse($appPath . '/appinfo/info.xml'); + + foreach ($info as $key => $value) { + if(is_array($value)) { + $value = json_encode($value); + } + if (in_array($key, $this->mandatoryFields)) { + $this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]); + continue; + } + + if (in_array($key, $this->optionalFields)) { + $this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]); + continue; + } + + if (in_array($key, $this->deprecatedFields)) { + // skip empty arrays - empty arrays for remote and public are always added + if($value === '[]' && in_array($key, ['public', 'remote', 'info'])) { + continue; + } + $this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]); + continue; + } + + $this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]); + } + + foreach ($this->mandatoryFields as $key) { + if(!isset($info[$key])) { + $this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]); + $errors[] = [ + 'type' => 'mandatoryFieldMissing', + 'field' => $key, + ]; + } + } + + $versionFile = $appPath . '/appinfo/version'; + if (is_file($versionFile)) { + $version = trim(file_get_contents($versionFile)); + if(isset($info['version'])) { + if($info['version'] !== $version) { + $this->emit('InfoChecker', 'differentVersions', + [$version, $info['version']]); + $errors[] = [ + 'type' => 'differentVersions', + 'message' => 'appinfo/version: ' . $version . + ' - appinfo/info.xml: ' . $info['version'], + ]; + } else { + $this->emit('InfoChecker', 'sameVersions', [$versionFile]); + } + } else { + $this->emit('InfoChecker', 'migrateVersion', [$version]); + } + } else { + if(!isset($info['version'])) { + $this->emit('InfoChecker', 'mandatoryFieldMissing', ['version']); + $errors[] = [ + 'type' => 'mandatoryFieldMissing', + 'field' => 'version', + ]; + } + } + + return $errors; + } +} diff --git a/lib/private/appframework/utility/simplecontainer.php b/lib/private/appframework/utility/simplecontainer.php index 5d7ea48752b..3de6d9ba5bc 100644 --- a/lib/private/appframework/utility/simplecontainer.php +++ b/lib/private/appframework/utility/simplecontainer.php @@ -45,7 +45,7 @@ class SimpleContainer extends Container implements IContainer { /** * @param ReflectionClass $class the class to instantiate - * @return stdClass the created class + * @return \stdClass the created class */ private function buildClass(ReflectionClass $class) { $constructor = $class->getConstructor(); @@ -74,7 +74,7 @@ class SimpleContainer extends Container implements IContainer { * If a parameter is not registered in the container try to instantiate it * by using reflection to find out how to build the class * @param string $name the class name to resolve - * @return stdClass + * @return \stdClass * @throws QueryException if the class could not be found or instantiated */ public function resolve($name) { diff --git a/lib/private/connector/sabre/listenerplugin.php b/lib/private/connector/sabre/listenerplugin.php index d0d40f4dc86..ec628add28b 100644 --- a/lib/private/connector/sabre/listenerplugin.php +++ b/lib/private/connector/sabre/listenerplugin.php @@ -21,6 +21,9 @@ namespace OC\Connector\Sabre; +use OCP\AppFramework\Http; +use OCP\SabrePluginEvent; +use OCP\SabrePluginException; use Sabre\DAV\ServerPlugin; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -49,9 +52,16 @@ class ListenerPlugin extends ServerPlugin { * in case the system is in maintenance mode. * * @return bool + * @throws \Exception */ public function emitListener() { - $this->dispatcher->dispatch('OC\Connector\Sabre::beforeMethod'); + $event = new SabrePluginEvent(); + + $this->dispatcher->dispatch('OC\Connector\Sabre::beforeMethod', $event); + + if ($event->getStatusCode() !== Http::STATUS_OK) { + throw new SabrePluginException($event->getMessage(), $event->getStatusCode()); + } return true; } diff --git a/lib/private/db/querybuilder/quotehelper.php b/lib/private/db/querybuilder/quotehelper.php index 0735f313abc..4b62fee6a6c 100644 --- a/lib/private/db/querybuilder/quotehelper.php +++ b/lib/private/db/querybuilder/quotehelper.php @@ -52,7 +52,7 @@ class QuoteHelper { return (string) $string; } - if ($string === null || $string === '*') { + if ($string === null || $string === 'null' || $string === '*') { return $string; } diff --git a/lib/private/encryption/decryptall.php b/lib/private/encryption/decryptall.php index 1ff9c74ef84..c1875f16abd 100644 --- a/lib/private/encryption/decryptall.php +++ b/lib/private/encryption/decryptall.php @@ -80,7 +80,7 @@ class DecryptAll { $this->input = $input; $this->output = $output; - if ($user !== '' && $this->userManager->userExists($user) === false) { + if (!empty($user) && $this->userManager->userExists($user) === false) { $this->output->writeln('User "' . $user . '" does not exist. Please check the username and try again'); return false; } diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index a5ed5fd3996..2d579fa2b60 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -260,7 +260,7 @@ abstract class Common implements Storage { $dh = $this->opendir($path); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { - if ($file !== '.' and $file !== '..') { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($this->is_dir($path . '/' . $file)) { mkdir($target . '/' . $file); $this->addLocalFolder($path . '/' . $file, $target . '/' . $file); @@ -283,7 +283,7 @@ abstract class Common implements Storage { $dh = $this->opendir($dir); if (is_resource($dh)) { while (($item = readdir($dh)) !== false) { - if ($item == '.' || $item == '..') continue; + if (\OC\Files\Filesystem::isIgnoredDir($item)) continue; if (strstr(strtolower($item), strtolower($query)) !== false) { $files[] = $dir . '/' . $item; } diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php index 3676fe69131..4b6b08a16fd 100644 --- a/lib/private/files/storage/local.php +++ b/lib/private/files/storage/local.php @@ -283,7 +283,7 @@ class Local extends \OC\Files\Storage\Common { $files = array(); $physicalDir = $this->getSourcePath($dir); foreach (scandir($physicalDir) as $item) { - if ($item == '.' || $item == '..') + if (\OC\Files\Filesystem::isIgnoredDir($item)) continue; $physicalItem = $physicalDir . '/' . $item; diff --git a/lib/private/files/storage/polyfill/copydirectory.php b/lib/private/files/storage/polyfill/copydirectory.php index 1b4873a3a76..73c6d3d5436 100644 --- a/lib/private/files/storage/polyfill/copydirectory.php +++ b/lib/private/files/storage/polyfill/copydirectory.php @@ -72,7 +72,7 @@ trait CopyDirectory { $dh = $this->opendir($source); $result = true; while ($file = readdir($dh)) { - if ($file !== '.' and $file !== '..') { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($this->is_dir($source . '/' . $file)) { $this->mkdir($target . '/' . $file); $result = $this->copyRecursive($source . '/' . $file, $target . '/' . $file); diff --git a/lib/private/files/storage/wrapper/permissionsmask.php b/lib/private/files/storage/wrapper/permissionsmask.php index 50c3f2a6268..8d40d023630 100644 --- a/lib/private/files/storage/wrapper/permissionsmask.php +++ b/lib/private/files/storage/wrapper/permissionsmask.php @@ -66,7 +66,7 @@ class PermissionsMask extends Wrapper { } public function isSharable($path) { - return $this->checkMask(Constants::PERMISSION_SHARE) and parent::isSharable($parm); + return $this->checkMask(Constants::PERMISSION_SHARE) and parent::isSharable($path); } public function getPermissions($path) { diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php index 3dc3975fb2a..0c647ab44c6 100644 --- a/lib/private/files/type/detection.php +++ b/lib/private/files/type/detection.php @@ -49,15 +49,22 @@ class Detection implements IMimeTypeDetector { private $urlGenerator; /** @var string */ - private $configDir; + private $customConfigDir; + + /** @var string */ + private $defaultConfigDir; /** * @param IURLGenerator $urlGenerator - * @param string $configDir + * @param string $customConfigDir + * @param string $defaultConfigDir */ - public function __construct(IURLGenerator $urlGenerator, $configDir) { + public function __construct(IURLGenerator $urlGenerator, + $customConfigDir, + $defaultConfigDir) { $this->urlGenerator = $urlGenerator; - $this->configDir = $configDir; + $this->customConfigDir = $customConfigDir; + $this->defaultConfigDir = $defaultConfigDir; } /** @@ -71,7 +78,9 @@ class Detection implements IMimeTypeDetector { * @param string $mimetype * @param string|null $secureMimeType */ - public function registerType($extension, $mimetype, $secureMimeType = null) { + public function registerType($extension, + $mimetype, + $secureMimeType = null) { $this->mimetypes[$extension] = array($mimetype, $secureMimeType); $this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype; } @@ -102,10 +111,10 @@ class Detection implements IMimeTypeDetector { return; } - $this->mimeTypeAlias = json_decode(file_get_contents($this->configDir . '/mimetypealiases.dist.json'), true); + $this->mimeTypeAlias = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypealiases.dist.json'), true); - if (file_exists($this->configDir . '/mimetypealiases.json')) { - $custom = json_decode(file_get_contents($this->configDir . '/mimetypealiases.json'), true); + if (file_exists($this->customConfigDir . '/mimetypealiases.json')) { + $custom = json_decode(file_get_contents($this->customConfigDir . '/mimetypealiases.json'), true); $this->mimeTypeAlias = array_merge($this->mimeTypeAlias, $custom); } } @@ -126,15 +135,15 @@ class Detection implements IMimeTypeDetector { return; } - $mimetypemapping = json_decode(file_get_contents($this->configDir . '/mimetypemapping.dist.json'), true); + $mimetypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true); //Check if need to load custom mappings - if (file_exists($this->configDir . '/mimetypemapping.json')) { - $custom = json_decode(file_get_contents($this->configDir . '/mimetypemapping.json'), true); - $mimetypemapping = array_merge($mimetypemapping, $custom); + if (file_exists($this->customConfigDir . '/mimetypemapping.json')) { + $custom = json_decode(file_get_contents($this->customConfigDir . '/mimetypemapping.json'), true); + $mimetypeMapping = array_merge($mimetypeMapping, $custom); } - $this->registerTypeArray($mimetypemapping); + $this->registerTypeArray($mimetypeMapping); } /** diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 9afa9d40b20..95b688fef5c 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -153,7 +153,10 @@ class View { return '/'; } - if (strpos($path, $this->fakeRoot) !== 0) { + // missing slashes can cause wrong matches! + $root = rtrim($this->fakeRoot, '/') . '/'; + + if (strpos($path, $root) !== 0) { return null; } else { $path = substr($path, strlen($this->fakeRoot)); @@ -759,59 +762,72 @@ class View { $this->lockFile($path2, ILockingProvider::LOCK_SHARED); $this->lockFile($path1, ILockingProvider::LOCK_SHARED); + $lockTypePath1 = ILockingProvider::LOCK_SHARED; + $lockTypePath2 = ILockingProvider::LOCK_SHARED; - $exists = $this->file_exists($path2); - if ($this->shouldEmitHooks()) { - \OC_Hook::emit( - Filesystem::CLASSNAME, - Filesystem::signal_copy, - array( - Filesystem::signal_param_oldpath => $this->getHookPath($path1), - Filesystem::signal_param_newpath => $this->getHookPath($path2), - Filesystem::signal_param_run => &$run - ) - ); - $this->emit_file_hooks_pre($exists, $path2, $run); - } - if ($run) { - $mount1 = $this->getMount($path1); - $mount2 = $this->getMount($path2); - $storage1 = $mount1->getStorage(); - $internalPath1 = $mount1->getInternalPath($absolutePath1); - $storage2 = $mount2->getStorage(); - $internalPath2 = $mount2->getInternalPath($absolutePath2); - - $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE); - - if ($mount1->getMountPoint() == $mount2->getMountPoint()) { - if ($storage1) { - $result = $storage1->copy($internalPath1, $internalPath2); - } else { - $result = false; - } - } else { - $result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2); - } - - $this->updater->update($path2); - - $this->changeLock($path2, ILockingProvider::LOCK_SHARED); + try { - if ($this->shouldEmitHooks() && $result !== false) { + $exists = $this->file_exists($path2); + if ($this->shouldEmitHooks()) { \OC_Hook::emit( Filesystem::CLASSNAME, - Filesystem::signal_post_copy, + Filesystem::signal_copy, array( Filesystem::signal_param_oldpath => $this->getHookPath($path1), - Filesystem::signal_param_newpath => $this->getHookPath($path2) + Filesystem::signal_param_newpath => $this->getHookPath($path2), + Filesystem::signal_param_run => &$run ) ); - $this->emit_file_hooks_post($exists, $path2); + $this->emit_file_hooks_pre($exists, $path2, $run); } + if ($run) { + $mount1 = $this->getMount($path1); + $mount2 = $this->getMount($path2); + $storage1 = $mount1->getStorage(); + $internalPath1 = $mount1->getInternalPath($absolutePath1); + $storage2 = $mount2->getStorage(); + $internalPath2 = $mount2->getInternalPath($absolutePath2); + + $this->changeLock($path2, ILockingProvider::LOCK_EXCLUSIVE); + $lockTypePath2 = ILockingProvider::LOCK_EXCLUSIVE; + + if ($mount1->getMountPoint() == $mount2->getMountPoint()) { + if ($storage1) { + $result = $storage1->copy($internalPath1, $internalPath2); + } else { + $result = false; + } + } else { + $result = $storage2->copyFromStorage($storage1, $internalPath1, $internalPath2); + } - $this->unlockFile($path2, ILockingProvider::LOCK_SHARED); - $this->unlockFile($path1, ILockingProvider::LOCK_SHARED); + $this->updater->update($path2); + + $this->changeLock($path2, ILockingProvider::LOCK_SHARED); + $lockTypePath2 = ILockingProvider::LOCK_SHARED; + + if ($this->shouldEmitHooks() && $result !== false) { + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_copy, + array( + Filesystem::signal_param_oldpath => $this->getHookPath($path1), + Filesystem::signal_param_newpath => $this->getHookPath($path2) + ) + ); + $this->emit_file_hooks_post($exists, $path2); + } + + } + } catch (\Exception $e) { + $this->unlockFile($path2, $lockTypePath2); + $this->unlockFile($path1, $lockTypePath1); + throw $e; } + + $this->unlockFile($path2, $lockTypePath2); + $this->unlockFile($path1, $lockTypePath1); + } return $result; } @@ -1656,7 +1672,7 @@ class View { if ($trimmed === '') { throw new InvalidPathException($l10n->t('Empty filename is not allowed')); } - if ($trimmed === '.' || $trimmed === '..') { + if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { throw new InvalidPathException($l10n->t('Dot files are not allowed')); } diff --git a/lib/private/http/client/client.php b/lib/private/http/client/client.php index b0aff10a413..1907937e55e 100644 --- a/lib/private/http/client/client.php +++ b/lib/private/http/client/client.php @@ -62,7 +62,7 @@ class Client implements IClient { $dataDir = $this->config->getSystemValue('datadirectory'); $this->client->setDefaultOption('verify', $dataDir.'/'.$this->certificateManager->getCertificateBundle()); } else { - $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/config/ca-bundle.crt'); + $this->client->setDefaultOption('verify', \OC::$SERVERROOT . '/resources/config/ca-bundle.crt'); } $this->client->setDefaultOption('headers/User-Agent', 'ownCloud Server Crawler'); diff --git a/lib/private/lock/dblockingprovider.php b/lib/private/lock/dblockingprovider.php index bfa86a6920e..a08357a6024 100644 --- a/lib/private/lock/dblockingprovider.php +++ b/lib/private/lock/dblockingprovider.php @@ -58,9 +58,17 @@ class DBLockingProvider extends AbstractLockingProvider { $this->timeFactory = $timeFactory; } - protected function initLockField($path) { + /** + * Insert a file locking row if it does not exists. + * + * @param string $path + * @param int $lock + * @return int number of inserted rows + */ + + protected function initLockField($path, $lock = 0) { $expire = $this->getExpireTime(); - $this->connection->insertIfNotExist('*PREFIX*file_locks', ['key' => $path, 'lock' => 0, 'ttl' => $expire], ['key']); + return $this->connection->insertIfNotExist('*PREFIX*file_locks', ['key' => $path, 'lock' => $lock, 'ttl' => $expire], ['key']); } /** @@ -98,18 +106,23 @@ class DBLockingProvider extends AbstractLockingProvider { $this->logger->warning("Trying to acquire a lock for '$path' while inside a transition"); } - $this->initLockField($path); $expire = $this->getExpireTime(); if ($type === self::LOCK_SHARED) { - $result = $this->connection->executeUpdate( - 'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1, `ttl` = ? WHERE `key` = ? AND `lock` >= 0', - [$expire, $path] - ); + $result = $this->initLockField($path,1); + if ($result <= 0) { + $result = $this->connection->executeUpdate ( + 'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1, `ttl` = ? WHERE `key` = ? AND `lock` >= 0', + [$expire, $path] + ); + } } else { - $result = $this->connection->executeUpdate( - 'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 0', - [$expire, $path] - ); + $result = $this->initLockField($path,-1); + if ($result <= 0) { + $result = $this->connection->executeUpdate( + 'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 0', + [$expire, $path] + ); + } } if ($result !== 1) { throw new LockedException($path); @@ -122,7 +135,6 @@ class DBLockingProvider extends AbstractLockingProvider { * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE */ public function releaseLock($path, $type) { - $this->initLockField($path); if ($type === self::LOCK_SHARED) { $this->connection->executeUpdate( 'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` - 1 WHERE `key` = ? AND `lock` > 0', diff --git a/lib/private/preview.php b/lib/private/preview.php index db2a56f9fa5..de964b72df2 100644 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -772,12 +772,6 @@ class Preview { throw new NotFoundException('File not found.'); } - if ($cachedPath = $this->isCached($this->info->getId())) { - header('Content-Type: ' . $this->info->getMimetype()); - $this->userView->readfile($cachedPath); - return; - } - if (is_null($this->preview)) { $this->getPreview(); } @@ -1302,6 +1296,13 @@ class Preview { /** * @param array $args + */ + public static function post_delete_versions($args) { + self::post_delete($args, 'files/'); + } + + /** + * @param array $args * @param string $prefix */ public static function post_delete($args, $prefix = '') { diff --git a/lib/private/security/certificatemanager.php b/lib/private/security/certificatemanager.php index 4d470f69a66..ded81863a73 100644 --- a/lib/private/security/certificatemanager.php +++ b/lib/private/security/certificatemanager.php @@ -110,7 +110,7 @@ class CertificateManager implements ICertificateManager { } // Append the default certificates - $defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/config/ca-bundle.crt'); + $defaultCertificates = file_get_contents(\OC::$SERVERROOT . '/resources/config/ca-bundle.crt'); fwrite($fh_certs, $defaultCertificates); fclose($fh_certs); } diff --git a/lib/private/server.php b/lib/private/server.php index d5f4f532c1c..9f99ead849b 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -470,7 +470,9 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('MimeTypeDetector', function(Server $c) { return new \OC\Files\Type\Detection( $c->getURLGenerator(), - \OC::$configDir); + \OC::$SERVERROOT . '/config/', + \OC::$SERVERROOT . '/resources/config/' + ); }); $this->registerService('MimeTypeLoader', function(Server $c) { return new \OC\Files\Type\Loader( diff --git a/lib/private/templatelayout.php b/lib/private/templatelayout.php index 93bf6cbd307..ae3c1093b20 100644 --- a/lib/private/templatelayout.php +++ b/lib/private/templatelayout.php @@ -116,9 +116,14 @@ class OC_TemplateLayout extends OC_Template { } } $userDisplayName = OC_User::getDisplayName(); + $appsMgmtActive = strpos(\OC::$server->getRequest()->getRequestUri(), \OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')) === 0; + if ($appsMgmtActive) { + $l = \OC::$server->getL10N('lib'); + $this->assign('application', $l->t('Apps')); + } $this->assign('user_displayname', $userDisplayName); $this->assign('user_uid', OC_User::getUser()); - $this->assign('appsmanagement_active', strpos(\OC::$server->getRequest()->getRequestUri(), \OC::$server->getURLGenerator()->linkToRoute('settings.AppSettings.viewApps')) === 0 ); + $this->assign('appsmanagement_active', $appsMgmtActive); $this->assign('enableAvatars', $this->config->getSystemValue('enable_avatars', true)); $this->assign('userAvatarSet', \OC_Helper::userAvatarSet(OC_User::getUser())); } else if ($renderAs == 'error') { @@ -148,7 +153,7 @@ class OC_TemplateLayout extends OC_Template { } else { // Add the js files $jsFiles = self::findJavascriptFiles(OC_Util::$scripts); - $this->assign('jsfiles', array(), false); + $this->assign('jsfiles', array()); if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') { $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config', array('v' => self::$versionHash))); } diff --git a/lib/private/updater.php b/lib/private/updater.php index 71e9732c307..b33180c3425 100644 --- a/lib/private/updater.php +++ b/lib/private/updater.php @@ -279,13 +279,6 @@ class Updater extends BasicEmitter { throw new \Exception($e->getMessage()); } - // FIXME: Some users do not upload the new ca-bundle.crt, let's catch this - // in the update. For a newer release we shall use an integrity check after - // the update. - if(!file_exists(\OC::$configDir .'/ca-bundle.crt')) { - throw new \Exception('Please upload the ca-bundle.crt file into the \'config\' directory.'); - } - // create empty file in data dir, so we can later find // out that this is indeed an ownCloud data directory // (in case it didn't exist before) diff --git a/lib/private/user.php b/lib/private/user.php index e70734ece40..ee1ff6f3766 100644 --- a/lib/private/user.php +++ b/lib/private/user.php @@ -146,6 +146,10 @@ class OC_User { self::$_usedBackends[$backend] = new OC_User_Database(); self::getManager()->registerBackend(self::$_usedBackends[$backend]); break; + case 'dummy': + self::$_usedBackends[$backend] = new \Test\Util\User\Dummy(); + self::getManager()->registerBackend(self::$_usedBackends[$backend]); + break; default: \OCP\Util::writeLog('core', 'Adding default user backend ' . $backend . '.', \OCP\Util::DEBUG); $className = 'OC_USER_' . strToUpper($backend); diff --git a/lib/private/util.php b/lib/private/util.php index eb1de5be5a4..667d358655f 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -1433,7 +1433,7 @@ class OC_Util { if ($trimmed === '') { return false; } - if ($trimmed === '.' || $trimmed === '..') { + if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { return false; } foreach (str_split($trimmed) as $char) { diff --git a/lib/public/icontainer.php b/lib/public/icontainer.php index ffd1d16c97e..64d5a7d8c1a 100644 --- a/lib/public/icontainer.php +++ b/lib/public/icontainer.php @@ -31,6 +31,7 @@ namespace OCP; use Closure; +use OCP\AppFramework\QueryException; /** diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 8be23dff214..e37652c1adc 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -194,6 +194,12 @@ interface IServerContainer { public function getAppConfig(); /** + * @return \OCP\L10N\IFactory + * @since 8.2.0 + */ + public function getL10NFactory(); + + /** * get an L10N instance * @param string $app appid * @param string $lang diff --git a/lib/public/sabrepluginevent.php b/lib/public/sabrepluginevent.php new file mode 100644 index 00000000000..fed3237166d --- /dev/null +++ b/lib/public/sabrepluginevent.php @@ -0,0 +1,82 @@ +<?php +/** + * @author Joas Schilling <nickvergessen@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCP; + + +use OCP\AppFramework\Http; +use Symfony\Component\EventDispatcher\Event; + +/** + * @since 8.2.0 + */ +class SabrePluginEvent extends Event { + + /** @var int */ + protected $statusCode; + + /** @var string */ + protected $message; + + /** + * @since 8.2.0 + */ + public function __construct() { + $this->message = ''; + $this->statusCode = Http::STATUS_OK; + } + + /** + * @param int $statusCode + * @return self + * @since 8.2.0 + */ + public function setStatusCode($statusCode) { + $this->statusCode = (int) $statusCode; + return $this; + } + + /** + * @param string $message + * @return self + * @since 8.2.0 + */ + public function setMessage($message) { + $this->message = (string) $message; + return $this; + } + + /** + * @return int + * @since 8.2.0 + */ + public function getStatusCode() { + return $this->statusCode; + } + + /** + * @return string + * @since 8.2.0 + */ + public function getMessage() { + return $this->message; + } +} diff --git a/lib/public/sabrepluginexception.php b/lib/public/sabrepluginexception.php new file mode 100644 index 00000000000..5dba3b90a02 --- /dev/null +++ b/lib/public/sabrepluginexception.php @@ -0,0 +1,41 @@ +<?php +/** + * @author Joas Schilling <nickvergessen@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCP; + + +use Sabre\DAV\Exception; + +/** + * @since 8.2.0 + */ +class SabrePluginException extends Exception { + + /** + * Returns the HTTP statuscode for this exception + * + * @return int + * @since 8.2.0 + */ + public function getHTTPCode() { + return $this->code; + } +} diff --git a/config/ca-bundle.crt b/resources/config/ca-bundle.crt index c93d3c4d4a7..c93d3c4d4a7 100644 --- a/config/ca-bundle.crt +++ b/resources/config/ca-bundle.crt diff --git a/config/mimetypealiases.dist.json b/resources/config/mimetypealiases.dist.json index 2c9bdaa00c8..3d6c5edc132 100644 --- a/config/mimetypealiases.dist.json +++ b/resources/config/mimetypealiases.dist.json @@ -1,7 +1,7 @@ { "_comment" : "Array of mimetype aliases.", "_comment2": "Any changes you make here will be overwritten on an update of ownCloud.", - "_comment3": "Put any custom aliases in a new file mimetypealiases.json in this directory", + "_comment3": "Put any custom mappings in a new file mimetypealiases.json in the config/ folder of ownCloud", "_comment4": "After any change to mimetypealiases.json run:", "_comment5": "./occ maintenance:mimetypesjs", diff --git a/config/mimetypemapping.dist.json b/resources/config/mimetypemapping.dist.json index 48ec4a56dab..79b0ca65240 100644 --- a/config/mimetypemapping.dist.json +++ b/resources/config/mimetypemapping.dist.json @@ -4,7 +4,7 @@ "_comment3": "and the second (if present] is a secure alternative", "_comment4": "Any changes you make here will be overwritten on an update of ownCloud", - "_comment5": "Put any custom mappings in a new file mimetypemapping.json in this directory", + "_comment5": "Put any custom mappings in a new file mimetypemapping.json in the config/ folder of ownCloud", "3gp": ["video/3gpp"], diff --git a/settings/admin.php b/settings/admin.php index 38683438f3a..c8bf1d32749 100644 --- a/settings/admin.php +++ b/settings/admin.php @@ -122,6 +122,7 @@ $template->assign('allowPublicUpload', $appConfig->getValue('core', 'shareapi_al $template->assign('allowResharing', $appConfig->getValue('core', 'shareapi_allow_resharing', 'yes')); $template->assign('allowPublicMailNotification', $appConfig->getValue('core', 'shareapi_allow_public_notification', 'no')); $template->assign('allowMailNotification', $appConfig->getValue('core', 'shareapi_allow_mail_notification', 'no')); +$template->assign('allowShareDialogUserEnumeration', $appConfig->getValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes')); $template->assign('onlyShareWithGroupMembers', \OC\Share\Share::shareWithGroupMembersOnly()); $databaseOverload = (strpos(\OCP\Config::getSystemValue('dbtype'), 'sqlite') !== false); $template->assign('databaseOverload', $databaseOverload); diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 36088d9f8c2..bfb0d5d364d 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -265,6 +265,11 @@ if ($_['cronErrors']) { <br /> <em><?php p($l->t('These groups will still be able to receive shares, but not to initiate them.')); ?></em> </p> + <p class="<?php if ($_['shareAPIEnabled'] === 'no') p('hidden');?>"> + <input type="checkbox" name="shareapi_allow_share_dialog_user_enumeration" value="1" id="shareapi_allow_share_dialog_user_enumeration" + <?php if ($_['allowShareDialogUserEnumeration'] === 'yes') print_unescaped('checked="checked"'); ?> /> + <label for="shareapi_allow_share_dialog_user_enumeration"><?php p($l->t('Allow username autocompletion in share dialog. If this is disabled the full username needs to be entered.'));?></label><br /> + </p> <?php print_unescaped($_['fileSharingSettings']); ?> </div> diff --git a/tests/apps/testapp-infoxml-version-different/appinfo/info.xml b/tests/apps/testapp-infoxml-version-different/appinfo/info.xml new file mode 100644 index 00000000000..c765400a76f --- /dev/null +++ b/tests/apps/testapp-infoxml-version-different/appinfo/info.xml @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<info> + <id>testapp-infoxml-version</id> + <version>1.2.3</version> + <author>Jane</author> + <description>A b c</description> + <licence>Abc</licence> + <name>Test app</name> +</info> diff --git a/tests/apps/testapp-infoxml-version-different/appinfo/version b/tests/apps/testapp-infoxml-version-different/appinfo/version new file mode 100644 index 00000000000..e8ea05db814 --- /dev/null +++ b/tests/apps/testapp-infoxml-version-different/appinfo/version @@ -0,0 +1 @@ +1.2.4 diff --git a/tests/apps/testapp-infoxml-version/appinfo/info.xml b/tests/apps/testapp-infoxml-version/appinfo/info.xml new file mode 100644 index 00000000000..c765400a76f --- /dev/null +++ b/tests/apps/testapp-infoxml-version/appinfo/info.xml @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<info> + <id>testapp-infoxml-version</id> + <version>1.2.3</version> + <author>Jane</author> + <description>A b c</description> + <licence>Abc</licence> + <name>Test app</name> +</info> diff --git a/tests/apps/testapp-infoxml-version/appinfo/version b/tests/apps/testapp-infoxml-version/appinfo/version new file mode 100644 index 00000000000..0495c4a88ca --- /dev/null +++ b/tests/apps/testapp-infoxml-version/appinfo/version @@ -0,0 +1 @@ +1.2.3 diff --git a/tests/apps/testapp-infoxml/appinfo/info.xml b/tests/apps/testapp-infoxml/appinfo/info.xml new file mode 100644 index 00000000000..cb63a0fc76e --- /dev/null +++ b/tests/apps/testapp-infoxml/appinfo/info.xml @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<info> + <id>testapp-infoxml</id> + <version>1.2.3</version> + <author>Jane</author> + <description>A b c</description> + <licence>Abc</licence> + <name>Test app</name> +</info> diff --git a/tests/apps/testapp-name-missing/appinfo/info.xml b/tests/apps/testapp-name-missing/appinfo/info.xml new file mode 100644 index 00000000000..f0a62b8d380 --- /dev/null +++ b/tests/apps/testapp-name-missing/appinfo/info.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<info> + <id>testapp-version</id> + <version>1.1.1</version> + <author>Jane</author> + <description>A b c</description> + <licence>Abc</licence> +</info> diff --git a/tests/apps/testapp-version-missing/appinfo/info.xml b/tests/apps/testapp-version-missing/appinfo/info.xml new file mode 100644 index 00000000000..d7da3e07e36 --- /dev/null +++ b/tests/apps/testapp-version-missing/appinfo/info.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<info> + <id>testapp-version</id> + <author>Jane</author> + <description>A b c</description> + <licence>Abc</licence> + <name>Test app</name> +</info> diff --git a/tests/apps/testapp-version/appinfo/info.xml b/tests/apps/testapp-version/appinfo/info.xml new file mode 100644 index 00000000000..d7da3e07e36 --- /dev/null +++ b/tests/apps/testapp-version/appinfo/info.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<info> + <id>testapp-version</id> + <author>Jane</author> + <description>A b c</description> + <licence>Abc</licence> + <name>Test app</name> +</info> diff --git a/tests/apps/testapp-version/appinfo/version b/tests/apps/testapp-version/appinfo/version new file mode 100644 index 00000000000..0495c4a88ca --- /dev/null +++ b/tests/apps/testapp-version/appinfo/version @@ -0,0 +1 @@ +1.2.3 diff --git a/tests/lib/app/codechecker/infocheckertest.php b/tests/lib/app/codechecker/infocheckertest.php new file mode 100644 index 00000000000..59c1316b769 --- /dev/null +++ b/tests/lib/app/codechecker/infocheckertest.php @@ -0,0 +1,73 @@ +<?php +/** + * @author Morris Jobke <hey@morrisjobke.de> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OC\App\CodeChecker; + +use OC\App\InfoParser; +use Test\TestCase; + +class InfoCheckerTest extends TestCase { + /** @var InfoChecker */ + protected $infoChecker; + + public static function setUpBeforeClass() { + \OC::$APPSROOTS[] = [ + 'path' => \OC::$SERVERROOT . '/tests/apps', + 'url' => '/apps-test', + 'writable' => false, + ]; + } + + public static function tearDownAfterClass() { + // remove last element + array_pop(\OC::$APPSROOTS); + } + + protected function setUp() { + parent::setUp(); + $infoParser = new InfoParser(\OC::$server->getHTTPHelper(), \OC::$server->getURLGenerator()); + + $this->infoChecker = new InfoChecker($infoParser); + } + + public function appInfoData() { + return [ + ['testapp-infoxml', []], + ['testapp-version', []], + ['testapp-infoxml-version', []], + ['testapp-infoxml-version-different', [['type' => 'differentVersions', 'message' => 'appinfo/version: 1.2.4 - appinfo/info.xml: 1.2.3']]], + ['testapp-version-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'version']]], + ['testapp-name-missing', [['type' => 'mandatoryFieldMissing', 'field' => 'name']]], + ]; + } + + /** + * @dataProvider appInfoData + * + * @param $appId + * @param $expectedErrors + */ + public function testApps($appId, $expectedErrors) { + $errors = $this->infoChecker->analyse($appId); + + $this->assertEquals($expectedErrors, $errors); + } +} diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 94001291d86..b5f186c5416 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -60,7 +60,7 @@ class FileCache extends \Test_Cache { \OC_Config::setValue('cachedirectory', $datadir); \OC_User::clearBackends(); - \OC_User::useBackend(new \OC_User_Dummy()); + \OC_User::useBackend(new \Test\Util\User\Dummy()); //login \OC_User::createUser('test', 'test'); diff --git a/tests/lib/db/querybuilder/quotehelpertest.php b/tests/lib/db/querybuilder/quotehelpertest.php index 904b4c500db..b83d9eed2df 100644 --- a/tests/lib/db/querybuilder/quotehelpertest.php +++ b/tests/lib/db/querybuilder/quotehelpertest.php @@ -43,6 +43,10 @@ class QuoteHelperTest extends \Test\TestCase { [new Literal('literal'), 'literal'], [new Literal(1), '1'], [new Parameter(':param'), ':param'], + + // (string) 'null' is Doctrines way to set columns to null + // See https://github.com/owncloud/core/issues/19314 + ['null', 'null'], ]; } diff --git a/tests/lib/encryption/decryptalltest.php b/tests/lib/encryption/decryptalltest.php index c2a0711c0a0..ce5bcf1e5ae 100644 --- a/tests/lib/encryption/decryptalltest.php +++ b/tests/lib/encryption/decryptalltest.php @@ -82,11 +82,13 @@ class DecryptAllTest extends TestCase { * @dataProvider dataTrueFalse * @param bool $prepareResult */ - public function testDecryptAll($prepareResult) { + public function testDecryptAll($prepareResult, $user) { - $user = 'user1'; - - $this->userManager->expects($this->once())->method('userExists')->willReturn(true); + if (!empty($user)) { + $this->userManager->expects($this->once())->method('userExists')->willReturn(true); + } else { + $this->userManager->expects($this->never())->method('userExists'); + } /** @var DecryptAll | \PHPUnit_Framework_MockObject_MockObject | $instance */ $instance = $this->getMockBuilder('OC\Encryption\DecryptAll') ->setConstructorArgs( @@ -117,8 +119,10 @@ class DecryptAllTest extends TestCase { public function dataTrueFalse() { return [ - [true], - [false] + [true, 'user1'], + [false, 'user1'], + [true, ''], + [true, null] ]; } diff --git a/tests/lib/files/etagtest.php b/tests/lib/files/etagtest.php index c3d364d6800..1a11b29cf00 100644 --- a/tests/lib/files/etagtest.php +++ b/tests/lib/files/etagtest.php @@ -17,7 +17,7 @@ class EtagTest extends \Test\TestCase { private $tmpDir; /** - * @var \OC_User_Dummy $userBackend + * @var \Test\Util\User\Dummy $userBackend */ private $userBackend; @@ -35,7 +35,7 @@ class EtagTest extends \Test\TestCase { $this->tmpDir = \OC_Helper::tmpFolder(); \OC_Config::setValue('datadirectory', $this->tmpDir); - $this->userBackend = new \OC_User_Dummy(); + $this->userBackend = new \Test\Util\User\Dummy(); \OC_User::useBackend($this->userBackend); } diff --git a/tests/lib/files/filesystem.php b/tests/lib/files/filesystem.php index b7061bd19a0..cc01ed70b5d 100644 --- a/tests/lib/files/filesystem.php +++ b/tests/lib/files/filesystem.php @@ -72,7 +72,7 @@ class Filesystem extends \Test\TestCase { protected function setUp() { parent::setUp(); - $userBackend = new \OC_User_Dummy(); + $userBackend = new \Test\Util\User\Dummy(); $userBackend->createUser(self::TEST_FILESYSTEM_USER1, self::TEST_FILESYSTEM_USER1); $userBackend->createUser(self::TEST_FILESYSTEM_USER2, self::TEST_FILESYSTEM_USER2); \OC::$server->getUserManager()->registerBackend($userBackend); @@ -274,7 +274,7 @@ class Filesystem extends \Test\TestCase { $user = \OC_User::getUser(); } else { $user = self::TEST_FILESYSTEM_USER1; - $backend = new \OC_User_Dummy(); + $backend = new \Test\Util\User\Dummy(); \OC_User::useBackend($backend); $backend->createUser($user, $user); $userObj = \OC::$server->getUserManager()->get($user); diff --git a/tests/lib/files/node/file.php b/tests/lib/files/node/file.php index e3b8019b4ca..c431a2eb366 100644 --- a/tests/lib/files/node/file.php +++ b/tests/lib/files/node/file.php @@ -18,7 +18,7 @@ class File extends \Test\TestCase { protected function setUp() { parent::setUp(); - $this->user = new \OC\User\User('', new \OC_User_Dummy); + $this->user = new \OC\User\User('', new \Test\Util\User\Dummy); } protected function getFileInfo($data) { diff --git a/tests/lib/files/node/folder.php b/tests/lib/files/node/folder.php index 96795cb02ef..b30f352847d 100644 --- a/tests/lib/files/node/folder.php +++ b/tests/lib/files/node/folder.php @@ -21,7 +21,7 @@ class Folder extends \Test\TestCase { protected function setUp() { parent::setUp(); - $this->user = new \OC\User\User('', new \OC_User_Dummy); + $this->user = new \OC\User\User('', new \Test\Util\User\Dummy); } protected function getFileInfo($data) { diff --git a/tests/lib/files/node/integration.php b/tests/lib/files/node/integration.php index 2d5ccd1fb85..5580b40a126 100644 --- a/tests/lib/files/node/integration.php +++ b/tests/lib/files/node/integration.php @@ -36,7 +36,7 @@ class IntegrationTests extends \Test\TestCase { \OC_Hook::clear('OC_Filesystem'); - $user = new User($this->getUniqueID('user'), new \OC_User_Dummy); + $user = new User($this->getUniqueID('user'), new \Test\Util\User\Dummy); $this->loginAsUser($user->getUID()); $this->view = new View(); diff --git a/tests/lib/files/node/node.php b/tests/lib/files/node/node.php index 01ed84c4a06..afcf4cbabaa 100644 --- a/tests/lib/files/node/node.php +++ b/tests/lib/files/node/node.php @@ -15,7 +15,7 @@ class Node extends \Test\TestCase { protected function setUp() { parent::setUp(); - $this->user = new \OC\User\User('', new \OC_User_Dummy); + $this->user = new \OC\User\User('', new \Test\Util\User\Dummy); } protected function getFileInfo($data) { diff --git a/tests/lib/files/node/root.php b/tests/lib/files/node/root.php index a763428209c..4b1aea1da4e 100644 --- a/tests/lib/files/node/root.php +++ b/tests/lib/files/node/root.php @@ -17,7 +17,7 @@ class Root extends \Test\TestCase { protected function setUp() { parent::setUp(); - $this->user = new \OC\User\User('', new \OC_User_Dummy); + $this->user = new \OC\User\User('', new \Test\Util\User\Dummy); } protected function getFileInfo($data) { diff --git a/tests/lib/files/storage/storage.php b/tests/lib/files/storage/storage.php index fcd7f73dcde..d381b4cdf40 100644 --- a/tests/lib/files/storage/storage.php +++ b/tests/lib/files/storage/storage.php @@ -573,4 +573,29 @@ abstract class Storage extends \Test\TestCase { $this->assertSameAsLorem($target); $this->assertTrue($this->instance->file_exists($source), $source . ' was deleted'); } + + public function testIsCreatable() { + $this->instance->mkdir('source'); + $this->assertTrue($this->instance->isCreatable('source')); + } + + public function testIsReadable() { + $this->instance->mkdir('source'); + $this->assertTrue($this->instance->isReadable('source')); + } + + public function testIsUpdatable() { + $this->instance->mkdir('source'); + $this->assertTrue($this->instance->isUpdatable('source')); + } + + public function testIsDeletable() { + $this->instance->mkdir('source'); + $this->assertTrue($this->instance->isDeletable('source')); + } + + public function testIsShareable() { + $this->instance->mkdir('source'); + $this->assertTrue($this->instance->isSharable('source')); + } } diff --git a/tests/lib/files/storage/wrapper/jail.php b/tests/lib/files/storage/wrapper/jail.php index a7bd684df44..9b16bc5a321 100644 --- a/tests/lib/files/storage/wrapper/jail.php +++ b/tests/lib/files/storage/wrapper/jail.php @@ -30,7 +30,7 @@ class Jail extends \Test\Files\Storage\Storage { $contents = array(); $dh = $this->sourceStorage->opendir(''); while ($file = readdir($dh)) { - if ($file !== '.' and $file !== '..') { + if (!\OC\Files\Filesystem::isIgnoredDir($file)) { $contents[] = $file; } } diff --git a/tests/lib/files/type/detection.php b/tests/lib/files/type/detection.php index 1997fa4dfd6..5800f4eb8e3 100644 --- a/tests/lib/files/type/detection.php +++ b/tests/lib/files/type/detection.php @@ -19,58 +19,64 @@ * */ -namespace OC\Files\Type; +namespace Test\Files\Type; use \OC\Files\Type\Detection; class DetectionTest extends \Test\TestCase { + /** @var Detection */ + private $detection; + + public function setUp() { + parent::setUp(); + $this->detection = new Detection( + \OC::$server->getURLGenerator(), + \OC::$SERVERROOT . '/config/', + \OC::$SERVERROOT . '/resources/config/' + ); + } public function testDetect() { - $detection = new Detection(\OC::$server->getURLGenerator(), \OC::$configDir); $dir = \OC::$SERVERROOT.'/tests/data'; - $result = $detection->detect($dir."/"); + $result = $this->detection->detect($dir."/"); $expected = 'httpd/unix-directory'; $this->assertEquals($expected, $result); - $result = $detection->detect($dir."/data.tar.gz"); + $result = $this->detection->detect($dir."/data.tar.gz"); $expected = 'application/x-gzip'; $this->assertEquals($expected, $result); - $result = $detection->detect($dir."/data.zip"); + $result = $this->detection->detect($dir."/data.zip"); $expected = 'application/zip'; $this->assertEquals($expected, $result); - $result = $detection->detect($dir."/testimagelarge.svg"); + $result = $this->detection->detect($dir."/testimagelarge.svg"); $expected = 'image/svg+xml'; $this->assertEquals($expected, $result); - $result = $detection->detect($dir."/testimage.png"); + $result = $this->detection->detect($dir."/testimage.png"); $expected = 'image/png'; $this->assertEquals($expected, $result); } public function testGetSecureMimeType() { - $detection = new Detection(\OC::$server->getURLGenerator(), \OC::$configDir); - - $result = $detection->getSecureMimeType('image/svg+xml'); + $result = $this->detection->getSecureMimeType('image/svg+xml'); $expected = 'text/plain'; $this->assertEquals($expected, $result); - $result = $detection->getSecureMimeType('image/png'); + $result = $this->detection->getSecureMimeType('image/png'); $expected = 'image/png'; $this->assertEquals($expected, $result); } public function testDetectPath() { - $detection = new Detection(\OC::$server->getURLGenerator(), \OC::$configDir); - - $this->assertEquals('text/plain', $detection->detectPath('foo.txt')); - $this->assertEquals('image/png', $detection->detectPath('foo.png')); - $this->assertEquals('image/png', $detection->detectPath('foo.bar.png')); - $this->assertEquals('application/octet-stream', $detection->detectPath('.png')); - $this->assertEquals('application/octet-stream', $detection->detectPath('foo')); - $this->assertEquals('application/octet-stream', $detection->detectPath('')); + $this->assertEquals('text/plain', $this->detection->detectPath('foo.txt')); + $this->assertEquals('image/png', $this->detection->detectPath('foo.png')); + $this->assertEquals('image/png', $this->detection->detectPath('foo.bar.png')); + $this->assertEquals('application/octet-stream', $this->detection->detectPath('.png')); + $this->assertEquals('application/octet-stream', $this->detection->detectPath('foo')); + $this->assertEquals('application/octet-stream', $this->detection->detectPath('')); } public function testDetectString() { @@ -78,16 +84,14 @@ class DetectionTest extends \Test\TestCase { $this->markTestSkipped('[Windows] Strings have mimetype application/octet-stream on Windows'); } - $detection = new Detection(\OC::$server->getURLGenerator(), \OC::$configDir); - - $result = $detection->detectString("/data/data.tar.gz"); + $result = $this->detection->detectString("/data/data.tar.gz"); $expected = 'text/plain; charset=us-ascii'; $this->assertEquals($expected, $result); } public function testMimeTypeIcon() { if (!class_exists('org\\bovigo\\vfs\\vfsStream')) { - $this->markTestSkipped('Pacakge vfsStream not installed'); + $this->markTestSkipped('Package vfsStream not installed'); } $confDir = \org\bovigo\vfs\vfsStream::setup(); $mimetypealiases_dist = \org\bovigo\vfs\vfsStream::newFile('mimetypealiases.dist.json')->at($confDir); @@ -111,7 +115,7 @@ class DetectionTest extends \Test\TestCase { ->with($this->equalTo('core'), $this->equalTo('filetypes/folder.png')) ->willReturn('folder.svg'); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('dir'); $this->assertEquals('folder.svg', $mimeType); @@ -130,7 +134,7 @@ class DetectionTest extends \Test\TestCase { ->with($this->equalTo('core'), $this->equalTo('filetypes/folder-shared.png')) ->willReturn('folder-shared.svg'); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('dir-shared'); $this->assertEquals('folder-shared.svg', $mimeType); @@ -150,7 +154,7 @@ class DetectionTest extends \Test\TestCase { ->with($this->equalTo('core'), $this->equalTo('filetypes/folder-external.png')) ->willReturn('folder-external.svg'); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('dir-external'); $this->assertEquals('folder-external.svg', $mimeType); @@ -170,7 +174,7 @@ class DetectionTest extends \Test\TestCase { ->with($this->equalTo('core'), $this->equalTo('filetypes/my-type.png')) ->willReturn('my-type.svg'); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('my-type'); $this->assertEquals('my-type.svg', $mimeType); @@ -200,7 +204,7 @@ class DetectionTest extends \Test\TestCase { } )); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('my-type'); $this->assertEquals('my.svg', $mimeType); @@ -231,7 +235,7 @@ class DetectionTest extends \Test\TestCase { } )); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('foo-bar'); $this->assertEquals('file.svg', $mimeType); @@ -250,7 +254,7 @@ class DetectionTest extends \Test\TestCase { ->with($this->equalTo('core'), $this->equalTo('filetypes/foo-bar.png')) ->willReturn('foo-bar.svg'); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('foo-bar'); $this->assertEquals('foo-bar.svg', $mimeType); $mimeType = $detection->mimeTypeIcon('foo-bar'); @@ -276,7 +280,7 @@ class DetectionTest extends \Test\TestCase { ->with($this->equalTo('core'), $this->equalTo('filetypes/foobar-baz.png')) ->willReturn('foobar-baz.svg'); - $detection = new Detection($urlGenerator, $confDir->url()); + $detection = new Detection($urlGenerator, $confDir->url(), $confDir->url()); $mimeType = $detection->mimeTypeIcon('foo'); $this->assertEquals('foobar-baz.svg', $mimeType); } diff --git a/tests/lib/files/utils/scanner.php b/tests/lib/files/utils/scanner.php index 75cd75ee3f5..5492774f42e 100644 --- a/tests/lib/files/utils/scanner.php +++ b/tests/lib/files/utils/scanner.php @@ -42,14 +42,14 @@ class TestScanner extends \OC\Files\Utils\Scanner { class Scanner extends \Test\TestCase { /** - * @var \OC_User_Dummy + * @var \Test\Util\User\Dummy */ private $userBackend; protected function setUp() { parent::setUp(); - $this->userBackend = new \OC_User_Dummy(); + $this->userBackend = new \Test\Util\User\Dummy(); \OC::$server->getUserManager()->registerBackend($this->userBackend); $this->loginAsUser(); } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index bb42f385fc5..ceeb9ba7a94 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -68,7 +68,7 @@ class View extends \Test\TestCase { \OC_Hook::clear(); \OC_User::clearBackends(); - \OC_User::useBackend(new \OC_User_Dummy()); + \OC_User::useBackend(new \Test\Util\User\Dummy()); //login $userManager = \OC::$server->getUserManager(); @@ -193,7 +193,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testGetPath() { + public function testGetPath() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); @@ -219,7 +219,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testMountPointOverwrite() { + public function testMountPointOverwrite() { $storage1 = $this->getTestStorage(false); $storage2 = $this->getTestStorage(); $storage1->mkdir('substorage'); @@ -265,7 +265,7 @@ class View extends \Test\TestCase { $appConfig->setValue('core', 'shareapi_exclude_groups_list', $oldExcludeGroupsList); } - function testCacheIncompleteFolder() { + public function testCacheIncompleteFolder() { $storage1 = $this->getTestStorage(false); \OC\Files\Filesystem::clearMounts(); \OC\Files\Filesystem::mount($storage1, array(), '/incomplete'); @@ -300,7 +300,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testSearch() { + public function testSearch() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); @@ -350,7 +350,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testWatcher() { + public function testWatcher() { $storage1 = $this->getTestStorage(); \OC\Files\Filesystem::mount($storage1, array(), '/'); $storage1->getWatcher()->setPolicy(Watcher::CHECK_ALWAYS); @@ -371,7 +371,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testCopyBetweenStorageNoCross() { + public function testCopyBetweenStorageNoCross() { $storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross'); $storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross'); $this->copyBetweenStorages($storage1, $storage2); @@ -380,7 +380,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testCopyBetweenStorageCross() { + public function testCopyBetweenStorageCross() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $this->copyBetweenStorages($storage1, $storage2); @@ -389,7 +389,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testCopyBetweenStorageCrossNonLocal() { + public function testCopyBetweenStorageCrossNonLocal() { $storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal'); $storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal'); $this->copyBetweenStorages($storage1, $storage2); @@ -417,7 +417,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testMoveBetweenStorageNoCross() { + public function testMoveBetweenStorageNoCross() { $storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross'); $storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoCross'); $this->moveBetweenStorages($storage1, $storage2); @@ -426,7 +426,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testMoveBetweenStorageCross() { + public function testMoveBetweenStorageCross() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $this->moveBetweenStorages($storage1, $storage2); @@ -435,7 +435,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testMoveBetweenStorageCrossNonLocal() { + public function testMoveBetweenStorageCrossNonLocal() { $storage1 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal'); $storage2 = $this->getTestStorage(true, '\Test\Files\TemporaryNoLocal'); $this->moveBetweenStorages($storage1, $storage2); @@ -458,7 +458,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testUnlink() { + public function testUnlink() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); \OC\Files\Filesystem::mount($storage1, array(), '/'); @@ -481,7 +481,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testUnlinkRootMustFail() { + public function testUnlinkRootMustFail() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); \OC\Files\Filesystem::mount($storage1, array(), '/'); @@ -500,7 +500,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testTouch() { + public function testTouch() { $storage = $this->getTestStorage(true, '\Test\Files\TemporaryNoTouch'); \OC\Files\Filesystem::mount($storage, array(), '/'); @@ -524,7 +524,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testViewHooks() { + public function testViewHooks() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $defaultRoot = \OC\Files\Filesystem::getRoot(); @@ -590,7 +590,7 @@ class View extends \Test\TestCase { /** * @medium */ - function testViewHooksIfRootStartsTheSame() { + public function testViewHooksIfRootStartsTheSame() { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $defaultRoot = \OC\Files\Filesystem::getRoot(); @@ -851,24 +851,98 @@ class View extends \Test\TestCase { } /** - * @dataProvider relativePathProvider + * @dataProvider chrootRelativePathProvider */ - function testGetRelativePath($absolutePath, $expectedPath) { + function testChrootGetRelativePath($root, $absolutePath, $expectedPath) { $view = new \OC\Files\View('/files'); - // simulate a external storage mount point which has a trailing slash - $view->chroot('/files/'); + $view->chroot($root); $this->assertEquals($expectedPath, $view->getRelativePath($absolutePath)); } - function relativePathProvider() { + public function chrootRelativePathProvider() { + return $this->relativePathProvider('/'); + } + + /** + * @dataProvider initRelativePathProvider + */ + public function testInitGetRelativePath($root, $absolutePath, $expectedPath) { + $view = new \OC\Files\View($root); + $this->assertEquals($expectedPath, $view->getRelativePath($absolutePath)); + } + + public function initRelativePathProvider() { + return $this->relativePathProvider(null); + } + + public function relativePathProvider($missingRootExpectedPath) { return array( - array('/files/', '/'), - array('/files', '/'), - array('/files/0', '0'), - array('/files/false', 'false'), - array('/files/true', 'true'), - array('/files/test', 'test'), - array('/files/test/foo', 'test/foo'), + // No root - returns the path + array('', '/files', '/files'), + array('', '/files/', '/files/'), + + // Root equals path - / + array('/files/', '/files/', '/'), + array('/files/', '/files', '/'), + array('/files', '/files/', '/'), + array('/files', '/files', '/'), + + // False negatives: chroot fixes those by adding the leading slash. + // But setting them up with this root (instead of chroot($root)) + // will fail them, although they should be the same. + // TODO init should be fixed, so it also adds the leading slash + array('files/', '/files/', $missingRootExpectedPath), + array('files', '/files/', $missingRootExpectedPath), + array('files/', '/files', $missingRootExpectedPath), + array('files', '/files', $missingRootExpectedPath), + + // False negatives: Paths provided to the method should have a leading slash + // TODO input should be checked to have a leading slash + array('/files/', 'files/', null), + array('/files', 'files/', null), + array('/files/', 'files', null), + array('/files', 'files', null), + + // with trailing slashes + array('/files/', '/files/0', '0'), + array('/files/', '/files/false', 'false'), + array('/files/', '/files/true', 'true'), + array('/files/', '/files/test', 'test'), + array('/files/', '/files/test/foo', 'test/foo'), + + // without trailing slashes + // TODO false expectation: Should match "with trailing slashes" + array('/files', '/files/0', '/0'), + array('/files', '/files/false', '/false'), + array('/files', '/files/true', '/true'), + array('/files', '/files/test', '/test'), + array('/files', '/files/test/foo', '/test/foo'), + + // leading slashes + array('/files/', '/files_trashbin/', null), + array('/files', '/files_trashbin/', null), + array('/files/', '/files_trashbin', null), + array('/files', '/files_trashbin', null), + + // no leading slashes + array('files/', 'files_trashbin/', null), + array('files', 'files_trashbin/', null), + array('files/', 'files_trashbin', null), + array('files', 'files_trashbin', null), + + // mixed leading slashes + array('files/', '/files_trashbin/', null), + array('/files/', 'files_trashbin/', null), + array('files', '/files_trashbin/', null), + array('/files', 'files_trashbin/', null), + array('files/', '/files_trashbin', null), + array('/files/', 'files_trashbin', null), + array('files', '/files_trashbin', null), + array('/files', 'files_trashbin', null), + + array('files', 'files_trashbin/test', null), + array('/files', '/files_trashbin/test', null), + array('/files', 'files_trashbin/test', null), ); } @@ -1012,6 +1086,7 @@ class View extends \Test\TestCase { $storage2->expects($this->any()) ->method('fopen') ->will($this->returnCallback(function ($path, $mode) use ($storage2) { + /** @var \PHPUnit_Framework_MockObject_MockObject | \OC\Files\Storage\Temporary $storage2 */ $source = fopen($storage2->getSourcePath($path), $mode); return \OC\Files\Stream\Quota::wrap($source, 9); })); @@ -1020,7 +1095,7 @@ class View extends \Test\TestCase { $storage1->file_put_contents('foo.txt', '0123456789ABCDEFGH'); $storage1->mkdir('dirtomove'); $storage1->file_put_contents('dirtomove/indir1.txt', '0123456'); // fits - $storage1->file_put_contents('dirtomove/indir2.txt', '0123456789ABCDEFGH'); // doesn't fit + $storage1->file_put_contents('dirtomove/indir2.txt', '0123456789ABCDEFGH'); // doesn't fit $storage2->file_put_contents('existing.txt', '0123'); $storage1->getScanner()->scan(''); $storage2->getScanner()->scan(''); @@ -1296,7 +1371,7 @@ class View extends \Test\TestCase { $thrown = false; try { - // this actually acquires two locks, one on the mount point and one no the storage root, + // this actually acquires two locks, one on the mount point and one on the storage root, // but the one on the storage root will fail $view->lockFile('/mountpoint.txt', ILockingProvider::LOCK_SHARED); } catch (\OCP\Lock\LockedException $e) { @@ -1818,6 +1893,49 @@ class View extends \Test\TestCase { } /** + * simulate a failed copy operation. + * We expect that we catch the exception, free the lock and re-throw it. + * + * @expectedException \Exception + */ + public function testLockFileCopyException() { + $view = new \OC\Files\View('/' . $this->user . '/files/'); + + $storage = $this->getMockBuilder('\OC\Files\Storage\Temporary') + ->setMethods(['copy']) + ->getMock(); + + $sourcePath = 'original.txt'; + $targetPath = 'target.txt'; + + \OC\Files\Filesystem::mount($storage, array(), $this->user . '/'); + $storage->mkdir('files'); + $view->file_put_contents($sourcePath, 'meh'); + + $storage->expects($this->once()) + ->method('copy') + ->will($this->returnCallback( + function() { + throw new \Exception(); + } + )); + + $this->connectMockHooks('copy', $view, $sourcePath, $lockTypeSourcePre, $lockTypeSourcePost); + $this->connectMockHooks('copy', $view, $targetPath, $lockTypeTargetPre, $lockTypeTargetPost); + + $this->assertNull($this->getFileLockType($view, $sourcePath), 'Source file not locked before operation'); + $this->assertNull($this->getFileLockType($view, $targetPath), 'Target file not locked before operation'); + + try { + $view->copy($sourcePath, $targetPath); + } catch (\Exception $e) { + $this->assertNull($this->getFileLockType($view, $sourcePath), 'Source file not locked after operation'); + $this->assertNull($this->getFileLockType($view, $targetPath), 'Target file not locked after operation'); + throw $e; + } + } + + /** * Test rename operation: unlock first path when second path was locked */ public function testLockFileRenameUnlockOnException() { diff --git a/tests/lib/group.php b/tests/lib/group.php index 795de695513..066dddc738e 100644 --- a/tests/lib/group.php +++ b/tests/lib/group.php @@ -30,7 +30,7 @@ class Test_Group extends \Test\TestCase { } public function testSingleBackend() { - $userBackend = new \OC_User_Dummy(); + $userBackend = new \Test\Util\User\Dummy(); \OC_User::getManager()->registerBackend($userBackend); OC_Group::useBackend(new OC_Group_Dummy()); @@ -112,7 +112,7 @@ class Test_Group extends \Test\TestCase { public function testUsersInGroup() { OC_Group::useBackend(new OC_Group_Dummy()); - $userBackend = new \OC_User_Dummy(); + $userBackend = new \Test\Util\User\Dummy(); \OC_User::getManager()->registerBackend($userBackend); $group1 = $this->getUniqueID(); @@ -141,7 +141,7 @@ class Test_Group extends \Test\TestCase { } public function testMultiBackend() { - $userBackend = new \OC_User_Dummy(); + $userBackend = new \Test\Util\User\Dummy(); \OC_User::getManager()->registerBackend($userBackend); $backend1 = new OC_Group_Dummy(); $backend2 = new OC_Group_Dummy(); diff --git a/tests/lib/preview.php b/tests/lib/preview.php index 82ee8e2eca2..9e118014bac 100644 --- a/tests/lib/preview.php +++ b/tests/lib/preview.php @@ -61,7 +61,7 @@ class Preview extends TestCase { $userManager = \OC::$server->getUserManager(); $userManager->clearBackends(); - $backend = new \OC_User_Dummy(); + $backend = new \Test\Util\User\Dummy(); $userManager->registerBackend($backend); $backend->createUser(self::TEST_PREVIEW_USER1, self::TEST_PREVIEW_USER1); $this->loginAsUser(self::TEST_PREVIEW_USER1); diff --git a/tests/lib/preview/provider.php b/tests/lib/preview/provider.php index 02459b83bb3..5377f30df82 100644 --- a/tests/lib/preview/provider.php +++ b/tests/lib/preview/provider.php @@ -49,7 +49,7 @@ abstract class Provider extends \Test\TestCase { $userManager = \OC::$server->getUserManager(); $userManager->clearBackends(); - $backend = new \OC_User_Dummy(); + $backend = new \Test\Util\User\Dummy(); $userManager->registerBackend($backend); $userId = $this->getUniqueID(); diff --git a/tests/lib/testcase.php b/tests/lib/testcase.php index 854d5f4f65b..7e4890a46c2 100644 --- a/tests/lib/testcase.php +++ b/tests/lib/testcase.php @@ -193,7 +193,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase { static protected function tearDownAfterClassCleanStrayDataUnlinkDir($dir) { if ($dh = @opendir($dir)) { while (($file = readdir($dh)) !== false) { - if ($file === '..' || $file === '.') { + if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } $path = $dir . '/' . $file; diff --git a/tests/lib/traits/usertrait.php b/tests/lib/traits/usertrait.php index 401d8b8a832..229087a5200 100644 --- a/tests/lib/traits/usertrait.php +++ b/tests/lib/traits/usertrait.php @@ -13,7 +13,7 @@ namespace Test\Traits; */ trait UserTrait { /** - * @var \OC_User_Dummy|\OCP\UserInterface + * @var \Test\Util\User\Dummy|\OCP\UserInterface */ protected $userBackend; @@ -22,7 +22,7 @@ trait UserTrait { } protected function setUpUserTrait() { - $this->userBackend = new \OC_User_Dummy(); + $this->userBackend = new \Test\Util\User\Dummy(); \OC::$server->getUserManager()->registerBackend($this->userBackend); } diff --git a/tests/lib/user.php b/tests/lib/user.php index cb0c661b2a4..3c068be2826 100644 --- a/tests/lib/user.php +++ b/tests/lib/user.php @@ -18,7 +18,7 @@ class User extends TestCase { protected function setUp(){ parent::setUp(); - $this->backend = $this->getMock('\OC_User_Dummy'); + $this->backend = $this->getMock('\Test\Util\User\Dummy'); $manager = \OC_User::getManager(); $manager->registerBackend($this->backend); } diff --git a/tests/lib/user/avataruserdummy.php b/tests/lib/user/avataruserdummy.php index 738b10492ea..086adb6043f 100644 --- a/tests/lib/user/avataruserdummy.php +++ b/tests/lib/user/avataruserdummy.php @@ -20,7 +20,7 @@ * */ -class Avatar_User_Dummy extends \OC_User_Dummy { +class Avatar_User_Dummy extends \Test\Util\User\Dummy { public function canChangeAvatar($uid) { return true; } diff --git a/tests/lib/user/dummy.php b/tests/lib/user/dummy.php index fcc921de4b1..c6c79d7a860 100644 --- a/tests/lib/user/dummy.php +++ b/tests/lib/user/dummy.php @@ -23,6 +23,6 @@ class Test_User_Dummy extends Test_User_Backend { protected function setUp() { parent::setUp(); - $this->backend=new OC_User_Dummy(); + $this->backend=new \Test\Util\User\Dummy(); } } diff --git a/tests/lib/user/manager.php b/tests/lib/user/manager.php index cc8bcd65896..df673f581c4 100644 --- a/tests/lib/user/manager.php +++ b/tests/lib/user/manager.php @@ -11,7 +11,7 @@ namespace Test\User; class Manager extends \Test\TestCase { public function testGetBackends() { - $userDummyBackend = $this->getMock('\OC_User_Dummy'); + $userDummyBackend = $this->getMock('\Test\Util\User\Dummy'); $manager = new \OC\User\Manager(); $manager->registerBackend($userDummyBackend); $this->assertEquals([$userDummyBackend], $manager->getBackends()); @@ -23,9 +23,9 @@ class Manager extends \Test\TestCase { public function testUserExistsSingleBackendExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) @@ -39,9 +39,9 @@ class Manager extends \Test\TestCase { public function testUserExistsSingleBackendNotExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) @@ -61,18 +61,18 @@ class Manager extends \Test\TestCase { public function testUserExistsTwoBackendsSecondExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 */ - $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1 = $this->getMock('\Test\Util\User\Dummy'); $backend1->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) ->will($this->returnValue(false)); /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 */ - $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2 = $this->getMock('\Test\Util\User\Dummy'); $backend2->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) @@ -87,18 +87,18 @@ class Manager extends \Test\TestCase { public function testUserExistsTwoBackendsFirstExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 */ - $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1 = $this->getMock('\Test\Util\User\Dummy'); $backend1->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) ->will($this->returnValue(true)); /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 */ - $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2 = $this->getMock('\Test\Util\User\Dummy'); $backend2->expects($this->never()) ->method('userExists'); @@ -113,7 +113,7 @@ class Manager extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('checkPassword') ->with($this->equalTo('foo'), $this->equalTo('bar')) @@ -140,7 +140,7 @@ class Manager extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->never()) ->method('checkPassword'); @@ -156,9 +156,9 @@ class Manager extends \Test\TestCase { public function testGetOneBackendExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) @@ -172,9 +172,9 @@ class Manager extends \Test\TestCase { public function testGetOneBackendNotExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('userExists') ->with($this->equalTo('foo')) @@ -188,9 +188,9 @@ class Manager extends \Test\TestCase { public function testSearchOneBackend() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('getUsers') ->with($this->equalTo('fo')) @@ -207,18 +207,18 @@ class Manager extends \Test\TestCase { public function testSearchTwoBackendLimitOffset() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 */ - $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1 = $this->getMock('\Test\Util\User\Dummy'); $backend1->expects($this->once()) ->method('getUsers') ->with($this->equalTo('fo'), $this->equalTo(3), $this->equalTo(1)) ->will($this->returnValue(array('foo1', 'foo2'))); /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 */ - $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2 = $this->getMock('\Test\Util\User\Dummy'); $backend2->expects($this->once()) ->method('getUsers') ->with($this->equalTo('fo'), $this->equalTo(3), $this->equalTo(1)) @@ -237,9 +237,9 @@ class Manager extends \Test\TestCase { public function testCreateUserSingleBackendNotExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') ->will($this->returnValue(true)); @@ -265,9 +265,9 @@ class Manager extends \Test\TestCase { */ public function testCreateUserSingleBackendExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') ->will($this->returnValue(true)); @@ -288,9 +288,9 @@ class Manager extends \Test\TestCase { public function testCreateUserSingleBackendNotSupported() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') ->will($this->returnValue(false)); @@ -320,9 +320,9 @@ class Manager extends \Test\TestCase { */ public function testCreateUserTwoBackendExists() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend1 */ - $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1 = $this->getMock('\Test\Util\User\Dummy'); $backend1->expects($this->any()) ->method('implementsActions') ->will($this->returnValue(true)); @@ -336,9 +336,9 @@ class Manager extends \Test\TestCase { ->will($this->returnValue(false)); /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend2 */ - $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2 = $this->getMock('\Test\Util\User\Dummy'); $backend2->expects($this->any()) ->method('implementsActions') ->will($this->returnValue(true)); @@ -368,9 +368,9 @@ class Manager extends \Test\TestCase { public function testCountUsersOneBackend() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('countUsers') ->will($this->returnValue(7)); @@ -382,14 +382,14 @@ class Manager extends \Test\TestCase { $backend->expects($this->once()) ->method('getBackendName') - ->will($this->returnValue('Mock_OC_User_Dummy')); + ->will($this->returnValue('Mock_Test_Util_User_Dummy')); $manager = new \OC\User\Manager(); $manager->registerBackend($backend); $result = $manager->countUsers(); $keys = array_keys($result); - $this->assertTrue(strpos($keys[0], 'Mock_OC_User_Dummy') !== false); + $this->assertTrue(strpos($keys[0], 'Mock_Test_Util_User_Dummy') !== false); $users = array_shift($result); $this->assertEquals(7, $users); @@ -397,9 +397,9 @@ class Manager extends \Test\TestCase { public function testCountUsersTwoBackends() { /** - * @var \OC_User_Dummy | \PHPUnit_Framework_MockObject_MockObject $backend + * @var \Test\Util\User\Dummy | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend1 = $this->getMock('\OC_User_Dummy'); + $backend1 = $this->getMock('\Test\Util\User\Dummy'); $backend1->expects($this->once()) ->method('countUsers') ->will($this->returnValue(7)); @@ -410,9 +410,9 @@ class Manager extends \Test\TestCase { ->will($this->returnValue(true)); $backend1->expects($this->once()) ->method('getBackendName') - ->will($this->returnValue('Mock_OC_User_Dummy')); + ->will($this->returnValue('Mock_Test_Util_User_Dummy')); - $backend2 = $this->getMock('\OC_User_Dummy'); + $backend2 = $this->getMock('\Test\Util\User\Dummy'); $backend2->expects($this->once()) ->method('countUsers') ->will($this->returnValue(16)); @@ -423,7 +423,7 @@ class Manager extends \Test\TestCase { ->will($this->returnValue(true)); $backend2->expects($this->once()) ->method('getBackendName') - ->will($this->returnValue('Mock_OC_User_Dummy')); + ->will($this->returnValue('Mock_Test_Util_User_Dummy')); $manager = new \OC\User\Manager(); $manager->registerBackend($backend1); @@ -433,7 +433,7 @@ class Manager extends \Test\TestCase { //because the backends have the same class name, only one value expected $this->assertEquals(1, count($result)); $keys = array_keys($result); - $this->assertTrue(strpos($keys[0], 'Mock_OC_User_Dummy') !== false); + $this->assertTrue(strpos($keys[0], 'Mock_Test_Util_User_Dummy') !== false); $users = array_shift($result); //users from backends shall be summed up @@ -442,7 +442,7 @@ class Manager extends \Test\TestCase { public function testDeleteUser() { $manager = new \OC\User\Manager(); - $backend = new \OC_User_Dummy(); + $backend = new \Test\Util\User\Dummy(); $backend->createUser('foo', 'bar'); $manager->registerBackend($backend); diff --git a/tests/lib/user/session.php b/tests/lib/user/session.php index 4dc7f29c5b8..d9dace2ef05 100644 --- a/tests/lib/user/session.php +++ b/tests/lib/user/session.php @@ -20,7 +20,7 @@ class Session extends \Test\TestCase { ->with('user_id') ->will($this->returnValue('foo')); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('userExists') ->with('foo') @@ -41,7 +41,7 @@ class Session extends \Test\TestCase { ->with('user_id') ->will($this->returnValue('foo')); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('userExists') ->with('foo') @@ -62,7 +62,7 @@ class Session extends \Test\TestCase { ->with('user_id') ->will($this->returnValue(null)); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->never()) ->method('userExists'); @@ -82,7 +82,7 @@ class Session extends \Test\TestCase { $manager = $this->getMock('\OC\User\Manager'); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->once()) @@ -122,7 +122,7 @@ class Session extends \Test\TestCase { } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->once()) @@ -161,7 +161,7 @@ class Session extends \Test\TestCase { } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->once()) @@ -196,7 +196,7 @@ class Session extends \Test\TestCase { } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); $user->expects($this->never()) @@ -220,7 +220,7 @@ class Session extends \Test\TestCase { $manager = $this->getMock('\OC\User\Manager'); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $manager->expects($this->once()) ->method('checkPassword') @@ -257,7 +257,7 @@ class Session extends \Test\TestCase { } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); @@ -305,7 +305,7 @@ class Session extends \Test\TestCase { } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); @@ -347,7 +347,7 @@ class Session extends \Test\TestCase { } $manager = $this->getMock('\OC\User\Manager', $managerMethods, array()); - $backend = $this->getMock('OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $user = $this->getMock('\OC\User\User', array(), array('foo', $backend)); diff --git a/tests/lib/user/user.php b/tests/lib/user/user.php index b1df975b60f..bc1365d35bf 100644 --- a/tests/lib/user/user.php +++ b/tests/lib/user/user.php @@ -74,7 +74,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('setPassword') ->with($this->equalTo('foo'), $this->equalTo('bar')); @@ -97,7 +97,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->never()) ->method('setPassword'); @@ -182,7 +182,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('deleteUser') ->with($this->equalTo('foo')); @@ -195,7 +195,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('getHome') ->with($this->equalTo('foo')) @@ -216,7 +216,7 @@ class User extends \Test\TestCase { } public function testGetBackendClassName() { - $user = new \OC\User\User('foo', new \OC_User_Dummy()); + $user = new \OC\User\User('foo', new \Test\Util\User\Dummy()); $this->assertEquals('Dummy', $user->getBackendClassName()); $user = new \OC\User\User('foo', new \OC_User_Database()); $this->assertEquals('Database', $user->getBackendClassName()); @@ -226,7 +226,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->never()) ->method('getHome'); @@ -253,7 +253,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') @@ -273,7 +273,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') @@ -287,7 +287,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') @@ -307,7 +307,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->any()) ->method('implementsActions') @@ -393,7 +393,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('setPassword'); @@ -434,7 +434,7 @@ class User extends \Test\TestCase { /** * @var \OC_User_Backend | \PHPUnit_Framework_MockObject_MockObject $backend */ - $backend = $this->getMock('\OC_User_Dummy'); + $backend = $this->getMock('\Test\Util\User\Dummy'); $backend->expects($this->once()) ->method('deleteUser'); diff --git a/lib/private/user/dummy.php b/tests/lib/util/user/dummy.php index 3779f7b5ddf..6e23e22ab67 100644 --- a/lib/private/user/dummy.php +++ b/tests/lib/util/user/dummy.php @@ -25,10 +25,14 @@ * */ +namespace Test\Util\User; + +use OC_User_Backend; + /** * dummy user backend, does not keep state, only for testing use */ -class OC_User_Dummy extends OC_User_Backend implements \OCP\IUserBackend { +class Dummy extends OC_User_Backend implements \OCP\IUserBackend { private $users = array(); private $displayNames = array(); diff --git a/tests/settings/controller/userscontrollertest.php b/tests/settings/controller/userscontrollertest.php index 06065a8454e..6fab43d6a16 100644 --- a/tests/settings/controller/userscontrollertest.php +++ b/tests/settings/controller/userscontrollertest.php @@ -100,7 +100,7 @@ class UsersControllerTest extends \Test\TestCase { $admin ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('OC_User_Dummy')); + ->will($this->returnValue('\Test\Util\User\Dummy')); $bar = $this->getMockBuilder('\OC\User\User') ->disableOriginalConstructor()->getMock(); $bar @@ -120,7 +120,7 @@ class UsersControllerTest extends \Test\TestCase { $bar ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('OC_User_Dummy')); + ->will($this->returnValue('\Test\Util\User\Dummy')); $this->container['GroupManager'] ->expects($this->once()) @@ -175,7 +175,7 @@ class UsersControllerTest extends \Test\TestCase { 'quota' => 404, 'storageLocation' => '/home/admin', 'lastLogin' => 12000, - 'backend' => 'OC_User_Dummy', + 'backend' => '\Test\Util\User\Dummy', 'email' => 'admin@bar.com', 'isRestoreDisabled' => false, ), @@ -187,7 +187,7 @@ class UsersControllerTest extends \Test\TestCase { 'quota' => 2323, 'storageLocation' => '/home/bar', 'lastLogin' => 3999000, - 'backend' => 'OC_User_Dummy', + 'backend' => '\Test\Util\User\Dummy', 'email' => 'bar@dummy.com', 'isRestoreDisabled' => false, ), @@ -257,7 +257,7 @@ class UsersControllerTest extends \Test\TestCase { $admin ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('OC_User_Dummy')); + ->will($this->returnValue('\Test\Util\User\Dummy')); $bar = $this->getMockBuilder('\OC\User\User') ->disableOriginalConstructor()->getMock(); $bar @@ -277,7 +277,7 @@ class UsersControllerTest extends \Test\TestCase { $bar ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('OC_User_Dummy')); + ->will($this->returnValue('\Test\Util\User\Dummy')); $this->container['GroupManager'] ->expects($this->at(0)) @@ -343,7 +343,7 @@ class UsersControllerTest extends \Test\TestCase { 'quota' => 404, 'storageLocation' => '/home/admin', 'lastLogin' => 12000, - 'backend' => 'OC_User_Dummy', + 'backend' => '\Test\Util\User\Dummy', 'email' => 'admin@bar.com', 'isRestoreDisabled' => false, ], @@ -355,7 +355,7 @@ class UsersControllerTest extends \Test\TestCase { 'quota' => 2323, 'storageLocation' => '/home/bar', 'lastLogin' => 3999000, - 'backend' => 'OC_User_Dummy', + 'backend' => '\Test\Util\User\Dummy', 'email' => 'bar@dummy.com', 'isRestoreDisabled' => false, ], @@ -414,7 +414,7 @@ class UsersControllerTest extends \Test\TestCase { $admin ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('OC_User_Dummy')); + ->will($this->returnValue('\Test\Util\User\Dummy')); $bar = $this->getMockBuilder('\OC\User\User') ->disableOriginalConstructor()->getMock(); $bar @@ -434,7 +434,7 @@ class UsersControllerTest extends \Test\TestCase { $bar ->expects($this->once()) ->method('getBackendClassName') - ->will($this->returnValue('OC_User_Dummy')); + ->will($this->returnValue('\Test\Util\User\Dummy')); $this->container['UserManager'] ->expects($this->once()) @@ -474,7 +474,7 @@ class UsersControllerTest extends \Test\TestCase { 'quota' => 404, 'storageLocation' => '/home/admin', 'lastLogin' => 12000, - 'backend' => 'OC_User_Dummy', + 'backend' => '\Test\Util\User\Dummy', 'email' => 'admin@bar.com', 'isRestoreDisabled' => false, ), @@ -486,7 +486,7 @@ class UsersControllerTest extends \Test\TestCase { 'quota' => 2323, 'storageLocation' => '/home/bar', 'lastLogin' => 3999000, - 'backend' => 'OC_User_Dummy', + 'backend' => '\Test\Util\User\Dummy', 'email' => 'bar@dummy.com', 'isRestoreDisabled' => false, ), @@ -522,16 +522,12 @@ class UsersControllerTest extends \Test\TestCase { $this->container['UserManager'] ->expects($this->once()) ->method('getBackends') - ->will($this->returnValue([new \OC_User_Dummy(), new \OC_User_Database()])); + ->will($this->returnValue([new \Test\Util\User\Dummy(), new \OC_User_Database()])); $this->container['UserManager'] ->expects($this->once()) ->method('clearBackends'); $this->container['UserManager'] ->expects($this->once()) - ->method('registerBackend') - ->with(new \OC_User_Dummy()); - $this->container['UserManager'] - ->expects($this->once()) ->method('search') ->with('') ->will($this->returnValue([$user])); @@ -552,7 +548,7 @@ class UsersControllerTest extends \Test\TestCase { ) ) ); - $response = $this->container['UsersController']->index(0, 10, '','', 'OC_User_Dummy'); + $response = $this->container['UsersController']->index(0, 10, '','', '\Test\Util\User\Dummy'); $this->assertEquals($expectedResponse, $response); } @@ -562,7 +558,7 @@ class UsersControllerTest extends \Test\TestCase { $this->container['UserManager'] ->expects($this->once()) ->method('getBackends') - ->will($this->returnValue([new \OC_User_Dummy(), new \OC_User_Database()])); + ->will($this->returnValue([new \Test\Util\User\Dummy(), new \OC_User_Database()])); $this->container['UserManager'] ->expects($this->once()) ->method('search') @@ -570,7 +566,7 @@ class UsersControllerTest extends \Test\TestCase { ->will($this->returnValue([])); $expectedResponse = new DataResponse([]); - $response = $this->container['UsersController']->index(0, 10, '','', 'OC_User_Dummy'); + $response = $this->container['UsersController']->index(0, 10, '','', '\Test\Util\User\Dummy'); $this->assertEquals($expectedResponse, $response); } |