Listen for event during preview rendering and apply secure view options
Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Родитель
45fcd99ae3
Коммит
25fd88bcb0
|
@ -27,6 +27,7 @@ namespace OCA\Richdocuments\AppInfo;
|
|||
use OCA\Files_Sharing\Event\ShareLinkAccessedEvent;
|
||||
use OCA\Richdocuments\AppConfig;
|
||||
use OCA\Richdocuments\Capabilities;
|
||||
use OCA\Richdocuments\Listener\BeforeFetchPreviewListener;
|
||||
use OCA\Richdocuments\Listener\CSPListener;
|
||||
use OCA\Richdocuments\Listener\LoadViewerListener;
|
||||
use OCA\Richdocuments\Listener\ShareLinkListener;
|
||||
|
@ -52,6 +53,7 @@ use OCP\Files\Template\TemplateFileCreator;
|
|||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\IPreview;
|
||||
use OCP\Preview\BeforeFetchPreviewEvent;
|
||||
use OCP\Security\CSP\AddContentSecurityPolicyEvent;
|
||||
|
||||
class Application extends App implements IBootstrap {
|
||||
|
@ -70,6 +72,7 @@ class Application extends App implements IBootstrap {
|
|||
$context->registerEventListener(AddContentSecurityPolicyEvent::class, CSPListener::class);
|
||||
$context->registerEventListener(LoadViewer::class, LoadViewerListener::class);
|
||||
$context->registerEventListener(ShareLinkAccessedEvent::class, ShareLinkListener::class);
|
||||
$context->registerEventListener(BeforeFetchPreviewEvent::class, BeforeFetchPreviewListener::class);
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
|
|
|
@ -67,6 +67,7 @@ use OCP\Lock\LockedException;
|
|||
use OCP\PreConditionNotMetException;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager as IShareManager;
|
||||
use OCP\Share\IShare;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
|
||||
|
@ -234,7 +235,8 @@ class WopiController extends Controller {
|
|||
$response['TemplateSaveAs'] = $file->getName();
|
||||
}
|
||||
|
||||
if ($this->shouldWatermark($isPublic, $wopi->getEditorUid(), $fileId, $wopi)) {
|
||||
$share = $this->getShareForWopiToken($wopi);
|
||||
if ($this->permissionManager->shouldWatermark($file, $wopi->getEditorUid(), $share)) {
|
||||
$email = $user !== null && !$isPublic ? $user->getEMailAddress() : "";
|
||||
$replacements = [
|
||||
'userId' => $wopi->getEditorUid(),
|
||||
|
@ -318,62 +320,6 @@ class WopiController extends Controller {
|
|||
return $response;
|
||||
}
|
||||
|
||||
private function shouldWatermark($isPublic, $userId, $fileId, Wopi $wopi) {
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_enabled', 'no') === 'no') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($isPublic) {
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkAll', 'no') === 'yes') {
|
||||
return true;
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkRead', 'no') === 'yes' && !$wopi->getCanwrite()) {
|
||||
return true;
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkSecure', 'no') === 'yes' && $wopi->getHideDownload()) {
|
||||
return true;
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkTags', 'no') === 'yes') {
|
||||
$tags = $this->appConfig->getAppValueArray('watermark_linkTagsList');
|
||||
$fileTags = \OC::$server->getSystemTagObjectMapper()->getTagIdsForObjects([$fileId], 'files')[$fileId];
|
||||
foreach ($fileTags as $tagId) {
|
||||
if (in_array($tagId, $tags, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_shareAll', 'no') === 'yes') {
|
||||
$files = $this->rootFolder->getUserFolder($userId)->getById($fileId);
|
||||
if (count($files) !== 0 && $files[0]->getOwner()->getUID() !== $userId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_shareRead', 'no') === 'yes' && !$wopi->getCanwrite()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($userId !== null && $this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_allGroups', 'no') === 'yes') {
|
||||
$groups = $this->appConfig->getAppValueArray('watermark_allGroupsList');
|
||||
foreach ($groups as $group) {
|
||||
if (\OC::$server->getGroupManager()->isInGroup($userId, $group)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_allTags', 'no') === 'yes') {
|
||||
$tags = $this->appConfig->getAppValueArray('watermark_allTagsList');
|
||||
$fileTags = \OC::$server->getSystemTagObjectMapper()->getTagIdsForObjects([$fileId], 'files')[$fileId];
|
||||
foreach ($fileTags as $tagId) {
|
||||
if (in_array($tagId, $tags, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an access token and a fileId, returns the contents of the file.
|
||||
* Expects a valid token in access_token parameter.
|
||||
|
@ -842,6 +788,7 @@ class WopiController extends Controller {
|
|||
* @throws ShareNotFound
|
||||
*/
|
||||
private function getFileForWopiToken(Wopi $wopi) {
|
||||
$this->userScopeService->setUserScope($wopi->getEditorUid());
|
||||
if (!empty($wopi->getShare())) {
|
||||
$share = $this->shareManager->getShareByToken($wopi->getShare());
|
||||
$node = $share->getNode();
|
||||
|
@ -875,6 +822,15 @@ class WopiController extends Controller {
|
|||
return array_shift($files);
|
||||
}
|
||||
|
||||
private function getShareForWopiToken(Wopi $wopi): ?IShare {
|
||||
try {
|
||||
return $wopi->getShare() ? $this->shareManager->getShareByToken($wopi->getShare()) : null;
|
||||
} catch (ShareNotFound $e) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint to return the template file that is requested by collabora to create a new document
|
||||
*
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* 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
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace OCA\Richdocuments\Listener;
|
||||
|
||||
use OCA\Files_Sharing\SharedStorage;
|
||||
use OCA\Richdocuments\PermissionManager;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Preview\BeforeFetchPreviewEvent;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IShare;
|
||||
|
||||
class BeforeFetchPreviewListener implements IEventListener {
|
||||
private PermissionManager $permissionManager;
|
||||
private IUserSession $userSession;
|
||||
private IRequest $request;
|
||||
private IManager $shareManager;
|
||||
|
||||
public function __construct(PermissionManager $permissionManager, IUserSession $userSession, IRequest $request, IManager $shareManager) {
|
||||
$this->permissionManager = $permissionManager;
|
||||
$this->userSession = $userSession;
|
||||
$this->request = $request;
|
||||
$this->shareManager = $shareManager;
|
||||
}
|
||||
|
||||
public function handle(Event $event): void {
|
||||
if (!$event instanceof BeforeFetchPreviewEvent) {
|
||||
return;
|
||||
}
|
||||
$shareToken = $this->request->getParam('token');
|
||||
|
||||
$share = null;
|
||||
|
||||
// Get share for internal shares
|
||||
$storage = $event->getNode()->getStorage();
|
||||
if (!$shareToken && $storage->instanceOfStorage(SharedStorage::class)) {
|
||||
if (method_exists(IShare::class, 'getAttributes')) {
|
||||
/** @var SharedStorage $storage */
|
||||
$share = $storage->getShare();
|
||||
}
|
||||
}
|
||||
|
||||
// Get different share for public previews as the share from the node is only set for mounted shares
|
||||
try {
|
||||
$share = $shareToken ? $this->shareManager->getShareByToken($shareToken) : $share;
|
||||
} catch (ShareNotFound $e) {
|
||||
}
|
||||
|
||||
$userId = $this->userSession->getUser() ? $this->userSession->getUser()->getUID() : null;
|
||||
if ($this->permissionManager->shouldWatermark($event->getNode(), $userId, $share)) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,26 +23,38 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCA\Richdocuments;
|
||||
|
||||
use OCP\Constants;
|
||||
use OCP\Files\Node;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Share\IAttributes;
|
||||
use OCP\Share\IShare;
|
||||
use OCP\SystemTag\ISystemTagObjectMapper;
|
||||
|
||||
class PermissionManager {
|
||||
private AppConfig $config;
|
||||
private AppConfig $appConfig;
|
||||
private IConfig $config;
|
||||
private IGroupManager $groupManager;
|
||||
private IUserManager $userManager;
|
||||
private IUserSession $userSession;
|
||||
private ISystemTagObjectMapper $systemTagObjectMapper;
|
||||
|
||||
public function __construct(
|
||||
AppConfig $config,
|
||||
IGroupManager $groupManager,
|
||||
IUserManager $userManager,
|
||||
IUserSession $userSession
|
||||
AppConfig $appConfig,
|
||||
IConfig $config,
|
||||
IGroupManager $groupManager,
|
||||
IUserManager $userManager,
|
||||
IUserSession $userSession,
|
||||
ISystemTagObjectMapper $systemTagObjectMapper
|
||||
) {
|
||||
$this->appConfig = $appConfig;
|
||||
$this->config = $config;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->userManager = $userManager;
|
||||
$this->userSession = $userSession;
|
||||
$this->systemTagObjectMapper = $systemTagObjectMapper;
|
||||
}
|
||||
|
||||
private function userMatchesGroupList(?string $userId = null, ?array $groupList = []): bool {
|
||||
|
@ -75,7 +87,7 @@ class PermissionManager {
|
|||
}
|
||||
|
||||
public function isEnabledForUser(string $userId = null): bool {
|
||||
if ($this->userMatchesGroupList($userId, $this->config->getUseGroups())) {
|
||||
if ($this->userMatchesGroupList($userId, $this->appConfig->getUseGroups())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -83,7 +95,7 @@ class PermissionManager {
|
|||
}
|
||||
|
||||
public function userCanEdit(string $userId = null): bool {
|
||||
if ($this->userMatchesGroupList($userId, $this->config->getEditGroups())) {
|
||||
if ($this->userMatchesGroupList($userId, $this->appConfig->getEditGroups())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -91,10 +103,80 @@ class PermissionManager {
|
|||
}
|
||||
|
||||
public function userIsFeatureLocked(string $userId = null): bool {
|
||||
if ($this->config->isReadOnlyFeatureLocked() && !$this->userCanEdit($userId)) {
|
||||
if ($this->appConfig->isReadOnlyFeatureLocked() && !$this->userCanEdit($userId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function shouldWatermark(Node $node, ?string $userId = null, ?IShare $share = null): bool {
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_enabled', 'no') === 'no') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$fileId = $node->getId();
|
||||
|
||||
$isUpdatable = $node->isUpdateable() && (!$share || $share->getPermissions() & Constants::PERMISSION_UPDATE);
|
||||
|
||||
$hasShareAttributes = $share && method_exists($share, 'getAttributes') && $share->getAttributes() instanceof IAttributes;
|
||||
$isDisabledDownload = $hasShareAttributes && $share->getAttributes()->getAttribute('permissions', 'download') === false;
|
||||
$isHideDownload = $share && $share->getHideDownload();
|
||||
$isSecureView = $isDisabledDownload || $isHideDownload;
|
||||
|
||||
if ($share && $share->getShareType() === IShare::TYPE_LINK) {
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkAll', 'no') === 'yes') {
|
||||
return true;
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkRead', 'no') === 'yes' && !$isUpdatable) {
|
||||
return true;
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkSecure', 'no') === 'yes' && $isSecureView) {
|
||||
return true;
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_linkTags', 'no') === 'yes') {
|
||||
$tags = $this->appConfig->getAppValueArray('watermark_linkTagsList');
|
||||
$fileTags = $this->systemTagObjectMapper->getTagIdsForObjects([$fileId], 'files')[$fileId];
|
||||
foreach ($fileTags as $tagId) {
|
||||
if (in_array($tagId, $tags, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_shareAll', 'no') === 'yes') {
|
||||
if ($node->getOwner()->getUID() !== $userId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_shareRead', 'no') === 'yes' && !$isUpdatable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_shareDisabledDownload', 'no') === 'yes' && $isDisabledDownload) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($userId !== null && $this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_allGroups', 'no') === 'yes') {
|
||||
$groups = $this->appConfig->getAppValueArray('watermark_allGroupsList');
|
||||
foreach ($groups as $group) {
|
||||
if ($this->groupManager->isInGroup($userId, $group)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->config->getAppValue(AppConfig::WATERMARK_APP_NAMESPACE, 'watermark_allTags', 'no') === 'yes') {
|
||||
$tags = $this->appConfig->getAppValueArray('watermark_allTagsList');
|
||||
$fileTags = $this->systemTagObjectMapper->getTagIdsForObjects([$fileId], 'files')[$fileId];
|
||||
foreach ($fileTags as $tagId) {
|
||||
if (in_array($tagId, $tags, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,13 @@ use OCP\IGroupManager;
|
|||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\IUserSession;
|
||||
use OCP\SystemTag\ISystemTagObjectMapper;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class PermissionManagerTest extends TestCase {
|
||||
/** @var AppConfig|MockObject */
|
||||
private $appConfig;
|
||||
/** @var IConfig|MockObject */
|
||||
private $config;
|
||||
/** @var IGroupManager|MockObject */
|
||||
|
@ -45,15 +48,17 @@ class PermissionManagerTest extends TestCase {
|
|||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
$this->config = $this->createMock(AppConfig::class);
|
||||
$this->appConfig = $this->createMock(AppConfig::class);
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->groupManager = $this->createMock(IGroupManager::class);
|
||||
$this->userManager = $this->createMock(IUserManager::class);
|
||||
$this->userSession = $this->createMock(IUserSession::class);
|
||||
$this->permissionManager = new PermissionManager($this->config, $this->groupManager, $this->userManager, $this->userSession);
|
||||
$this->systemTagMapper = $this->createMock(ISystemTagObjectMapper::class);
|
||||
$this->permissionManager = new PermissionManager($this->appConfig, $this->config, $this->groupManager, $this->userManager, $this->userSession, $this->systemTagMapper);
|
||||
}
|
||||
|
||||
public function testIsEnabledForUserEnabledNoRestrictions(): void {
|
||||
$this->config
|
||||
$this->appConfig
|
||||
->expects($this->once())
|
||||
->method('getUseGroups')
|
||||
->willReturn(null);
|
||||
|
@ -77,7 +82,7 @@ class PermissionManagerTest extends TestCase {
|
|||
/** @dataProvider dataGroupMatchGroups */
|
||||
public function testEditGroups($editGroups, $userGroups, $result): void {
|
||||
$userMock = $this->createMock(IUser::class);
|
||||
$this->config->expects($this->any())
|
||||
$this->appConfig->expects($this->any())
|
||||
->method('getEditGroups')
|
||||
->willReturn($editGroups);
|
||||
$this->userManager->expects($this->any())
|
||||
|
@ -93,7 +98,7 @@ class PermissionManagerTest extends TestCase {
|
|||
/** @dataProvider dataGroupMatchGroups */
|
||||
public function testUseGroups($editGroups, $userGroups, $result): void {
|
||||
$userMock = $this->createMock(IUser::class);
|
||||
$this->config->expects($this->any())
|
||||
$this->appConfig->expects($this->any())
|
||||
->method('getUseGroups')
|
||||
->willReturn($editGroups);
|
||||
$this->userManager->expects($this->any())
|
||||
|
@ -109,10 +114,10 @@ class PermissionManagerTest extends TestCase {
|
|||
/** @dataProvider dataGroupMatchGroups */
|
||||
public function testFeatureLock($editGroups, $userGroups, $result): void {
|
||||
$userMock = $this->createMock(IUser::class);
|
||||
$this->config->expects($this->any())
|
||||
$this->appConfig->expects($this->any())
|
||||
->method('getEditGroups')
|
||||
->willReturn($editGroups);
|
||||
$this->config->expects($this->any())
|
||||
$this->appConfig->expects($this->any())
|
||||
->method('isReadOnlyFeatureLocked')
|
||||
->willReturn(true);
|
||||
$this->userManager->expects($this->any())
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
<code>OpenDocument</code>
|
||||
<code>Pdf</code>
|
||||
</MissingDependency>
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>BeforeFetchPreviewEvent</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Command/ActivateConfig.php">
|
||||
<RedundantCondition occurrences="1">
|
||||
|
@ -76,24 +79,16 @@
|
|||
<code>$item->getId()</code>
|
||||
<code>$node->getId()</code>
|
||||
</InvalidScalarArgument>
|
||||
<MissingDependency occurrences="7">
|
||||
<MissingDependency occurrences="5">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>BeforeFederationRedirectEvent</code>
|
||||
<code>IRootFolder</code>
|
||||
<code>IRootFolder</code>
|
||||
</MissingDependency>
|
||||
<RedundantCondition occurrences="1">
|
||||
<code>$app !== ''</code>
|
||||
</RedundantCondition>
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>\OCA\Files_Sharing\External\Storage</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedInterfaceMethod occurrences="1">
|
||||
<code>getRemote</code>
|
||||
</UndefinedInterfaceMethod>
|
||||
</file>
|
||||
<file src="lib/Controller/OCSController.php">
|
||||
<MissingDependency occurrences="4">
|
||||
|
@ -129,9 +124,7 @@
|
|||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="lib/Controller/WopiController.php">
|
||||
<MissingDependency occurrences="13">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<MissingDependency occurrences="11">
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
<code>$this->rootFolder</code>
|
||||
|
@ -159,6 +152,16 @@
|
|||
<code>$time</code>
|
||||
</InvalidScalarArgument>
|
||||
</file>
|
||||
<file src="lib/Listener/BeforeFetchPreviewListener.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<code>BeforeFetchPreviewEvent</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/PermissionManager.php">
|
||||
<RedundantCondition occurrences="1">
|
||||
<code>$share && method_exists($share, 'getAttributes')</code>
|
||||
</RedundantCondition>
|
||||
</file>
|
||||
<file src="lib/Preview/MSExcel.php">
|
||||
<MissingDependency occurrences="1">
|
||||
<code>Office</code>
|
||||
|
|
|
@ -3,31 +3,40 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\Federation {
|
||||
class TrustedServers {
|
||||
public function getServers() {}
|
||||
public function isTrustedServer($domainWithPort) {}
|
||||
}
|
||||
class TrustedServers {
|
||||
public function getServers() {
|
||||
}
|
||||
public function isTrustedServer($domainWithPort) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace OCA\Viewer\Event {
|
||||
class LoadViewer extends \OCP\EventDispatcher\Event {}
|
||||
class LoadViewer extends \OCP\EventDispatcher\Event {
|
||||
}
|
||||
}
|
||||
|
||||
namespace Doctrine\DBAL\Platforms {
|
||||
class SqlitePlatform {}
|
||||
class SqlitePlatform {
|
||||
}
|
||||
}
|
||||
|
||||
namespace OCA\Files_Sharing {
|
||||
use OCP\Files\Storage\IStorage;
|
||||
use \OCP\Share\IShare;
|
||||
class SharedStorage {
|
||||
public function getShare(): IShare {}
|
||||
|
||||
abstract class SharedStorage implements IStorage {
|
||||
public function getShare(): IShare {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace OCA\Files_Sharing\Event {
|
||||
use \OCP\Share\IShare;
|
||||
|
||||
class ShareLinkAccessedEvent extends \OCP\EventDispatcher\Event {
|
||||
public function __construct(IShare $share, string $step = '', int $errorCode = 200, string $errorMessage = '') {}
|
||||
public function __construct(IShare $share, string $step = '', int $errorCode = 200, string $errorMessage = '') {
|
||||
}
|
||||
|
||||
public function getShare(): IShare {
|
||||
}
|
||||
|
@ -44,5 +53,6 @@ namespace OCA\Files_Sharing\Event {
|
|||
}
|
||||
|
||||
class OC_Helper {
|
||||
public static function getFileTemplateManager() {}
|
||||
public static function getFileTemplateManager() {
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче