Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
'OCA\\Files_Sharing\\Controller\\ShareController' => $baseDir . '/../lib/Controller/ShareController.php',
'OCA\\Files_Sharing\\Controller\\ShareInfoController' => $baseDir . '/../lib/Controller/ShareInfoController.php',
'OCA\\Files_Sharing\\Controller\\ShareesAPIController' => $baseDir . '/../lib/Controller/ShareesAPIController.php',
'OCA\\Files_Sharing\\DefaultPublicShareTemplateProvider' => $baseDir . '/../lib/DefaultPublicShareTemplateProvider.php',
'OCA\\Files_Sharing\\DeleteOrphanedSharesJob' => $baseDir . '/../lib/DeleteOrphanedSharesJob.php',
'OCA\\Files_Sharing\\Event\\BeforeTemplateRenderedEvent' => $baseDir . '/../lib/Event/BeforeTemplateRenderedEvent.php',
'OCA\\Files_Sharing\\Event\\ShareLinkAccessedEvent' => $baseDir . '/../lib/Event/ShareLinkAccessedEvent.php',
Expand Down
1 change: 1 addition & 0 deletions apps/files_sharing/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class ComposerStaticInitFiles_Sharing
'OCA\\Files_Sharing\\Controller\\ShareController' => __DIR__ . '/..' . '/../lib/Controller/ShareController.php',
'OCA\\Files_Sharing\\Controller\\ShareInfoController' => __DIR__ . '/..' . '/../lib/Controller/ShareInfoController.php',
'OCA\\Files_Sharing\\Controller\\ShareesAPIController' => __DIR__ . '/..' . '/../lib/Controller/ShareesAPIController.php',
'OCA\\Files_Sharing\\DefaultPublicShareTemplateProvider' => __DIR__ . '/..' . '/../lib/DefaultPublicShareTemplateProvider.php',
'OCA\\Files_Sharing\\DeleteOrphanedSharesJob' => __DIR__ . '/..' . '/../lib/DeleteOrphanedSharesJob.php',
'OCA\\Files_Sharing\\Event\\BeforeTemplateRenderedEvent' => __DIR__ . '/..' . '/../lib/Event/BeforeTemplateRenderedEvent.php',
'OCA\\Files_Sharing\\Event\\ShareLinkAccessedEvent' => __DIR__ . '/..' . '/../lib/Event/ShareLinkAccessedEvent.php',
Expand Down
250 changes: 33 additions & 217 deletions apps/files_sharing/lib/Controller/ShareController.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IManager as ShareManager;
use OCP\Share\IShare;
use OCP\Share\IPublicShareTemplateFactory;
use OCP\Template;

/**
Expand All @@ -99,24 +100,28 @@ class ShareController extends AuthPublicShareController {
protected ShareManager $shareManager;
protected ISecureRandom $secureRandom;
protected ?Share\IShare $share = null;

public function __construct(string $appName,
IRequest $request,
IConfig $config,
IURLGenerator $urlGenerator,
IUserManager $userManager,
ILogger $logger,
\OCP\Activity\IManager $activityManager,
ShareManager $shareManager,
ISession $session,
IPreview $previewManager,
IRootFolder $rootFolder,
FederatedShareProvider $federatedShareProvider,
IAccountManager $accountManager,
IEventDispatcher $eventDispatcher,
IL10N $l10n,
ISecureRandom $secureRandom,
Defaults $defaults) {
private IPublicShareTemplateFactory $publicShareTemplateFactory;

public function __construct(
string $appName,
IRequest $request,
IConfig $config,
IURLGenerator $urlGenerator,
IUserManager $userManager,
ILogger $logger,

Check notice

Code scanning / Psalm

DeprecatedClass

Class OCP\ILogger is marked as deprecated
\OCP\Activity\IManager $activityManager,
ShareManager $shareManager,
ISession $session,
IPreview $previewManager,
IRootFolder $rootFolder,
FederatedShareProvider $federatedShareProvider,
IAccountManager $accountManager,
IEventDispatcher $eventDispatcher,
IL10N $l10n,
ISecureRandom $secureRandom,
Defaults $defaults,
IPublicShareTemplateFactory $publicShareTemplateFactory
) {
parent::__construct($appName, $request, $session, $urlGenerator);

$this->config = $config;
Expand All @@ -132,6 +137,7 @@ public function __construct(string $appName,
$this->secureRandom = $secureRandom;
$this->defaults = $defaults;
$this->shareManager = $shareManager;
$this->publicShareTemplateFactory = $publicShareTemplateFactory;
}

public const SHARE_ACCESS = 'access';
Expand Down Expand Up @@ -367,6 +373,15 @@ public function showShare($path = ''): TemplateResponse {

$shareNode = $share->getNode();

try {
$templateProvider = $this->publicShareTemplateFactory->getProvider($share);
$response = $templateProvider->renderPage($share, $this->getToken(), $path);
} catch (NotFoundException $e) {
$this->emitAccessShareHook($share, 404, 'Share not found');

Check notice

Code scanning / Psalm

DeprecatedMethod

The method OCA\Files_Sharing\Controller\ShareController::emitAccessShareHook has been marked as deprecated
$this->emitShareAccessEvent($share, ShareController::SHARE_ACCESS, 404, 'Share not found');
throw new NotFoundException();
}

// We can't get the path of a file share
try {
if ($shareNode instanceof \OCP\Files\File && $path !== '') {
Expand All @@ -380,205 +395,6 @@ public function showShare($path = ''): TemplateResponse {
throw $e;
}

$shareTmpl = [];
$shareTmpl['owner'] = '';
$shareTmpl['shareOwner'] = '';

$owner = $this->userManager->get($share->getShareOwner());
if ($owner instanceof IUser) {
$ownerAccount = $this->accountManager->getAccount($owner);

$ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
if ($ownerName->getScope() === IAccountManager::SCOPE_PUBLISHED) {
$shareTmpl['owner'] = $owner->getUID();
$shareTmpl['shareOwner'] = $owner->getDisplayName();
}
}

$shareTmpl['filename'] = $shareNode->getName();
$shareTmpl['directory_path'] = $share->getTarget();
$shareTmpl['note'] = $share->getNote();
$shareTmpl['mimetype'] = $shareNode->getMimetype();
$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
$shareTmpl['dirToken'] = $this->getToken();
$shareTmpl['sharingToken'] = $this->getToken();
$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
$shareTmpl['dir'] = '';
$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
$shareTmpl['hideDownload'] = $share->getHideDownload();

$hideFileList = false;

if ($shareNode instanceof \OCP\Files\Folder) {
$shareIsFolder = true;

try {
$folderNode = $shareNode->get($path);
} catch (\OCP\Files\NotFoundException $e) {
$this->emitAccessShareHook($share, 404, 'Share not found');
$this->emitShareAccessEvent($share, self::SHARE_ACCESS, 404, 'Share not found');
throw new NotFoundException();
}

$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());

/*
* The OC_Util methods require a view. This just uses the node API
*/
$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
$freeSpace = (int)max($freeSpace, 0);
} else {
$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
}

$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
$maxUploadFilesize = $freeSpace;

$folder = new Template('files', 'list', '');

$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
$folder->assign('dirToken', $this->getToken());
$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
$folder->assign('isPublic', true);
$folder->assign('hideFileList', $hideFileList);
$folder->assign('publicUploadEnabled', 'no');
// default to list view
$folder->assign('showgridview', false);
$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
$folder->assign('freeSpace', $freeSpace);
$folder->assign('usedSpacePercent', 0);
$folder->assign('trash', false);
$shareTmpl['folder'] = $folder->fetchPage();
} else {
$shareIsFolder = false;
}

// default to list view
$shareTmpl['showgridview'] = false;

$shareTmpl['hideFileList'] = $hideFileList;
$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', [
'token' => $this->getToken(),
'filename' => $shareIsFolder ? null : $shareNode->getName()
]);
$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];

if ($shareTmpl['previewSupported']) {
$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
$ogPreview = $shareTmpl['previewImage'];

// We just have direct previews for image files
if ($shareNode->getMimePart() === 'image') {
$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);

$ogPreview = $shareTmpl['previewURL'];

//Whatapp is kind of picky about their size requirements
if ($this->request->isUserAgent(['/^WhatsApp/'])) {
$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
'token' => $this->getToken(),
'x' => 256,
'y' => 256,
'a' => true,
]);
}
}
} else {
$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
$ogPreview = $shareTmpl['previewImage'];
}

// Load files we need
\OCP\Util::addScript('files', 'semaphore');
\OCP\Util::addScript('files', 'file-upload');
\OCP\Util::addStyle('files_sharing', 'publicView');
\OCP\Util::addScript('files_sharing', 'public');
\OCP\Util::addScript('files_sharing', 'templates');
\OCP\Util::addScript('files', 'fileactions');
\OCP\Util::addScript('files', 'fileactionsmenu');
\OCP\Util::addScript('files', 'jquery.fileupload');
\OCP\Util::addScript('files_sharing', 'files_drop');

if (isset($shareTmpl['folder'])) {
// JS required for folders
\OCP\Util::addStyle('files', 'merged');
\OCP\Util::addScript('files', 'filesummary');
\OCP\Util::addScript('files', 'templates');
\OCP\Util::addScript('files', 'breadcrumb');
\OCP\Util::addScript('files', 'fileinfomodel');
\OCP\Util::addScript('files', 'newfilemenu');
\OCP\Util::addScript('files', 'files');
\OCP\Util::addScript('files', 'filemultiselectmenu');
\OCP\Util::addScript('files', 'filelist');
\OCP\Util::addScript('files', 'keyboardshortcuts');
\OCP\Util::addScript('files', 'operationprogressbar');
}

// Load Viewer scripts
if (class_exists(LoadViewer::class)) {
$this->eventDispatcher->dispatchTyped(new LoadViewer());
}
// OpenGraph Support: http://ogp.me/
\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);

$this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($share));

$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
$csp->addAllowedFrameDomain('\'self\'');

$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
$response->setHeaderTitle($shareTmpl['filename']);
if ($shareTmpl['shareOwner'] !== '') {
$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
}

$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;

if ($isNoneFileDropFolder && !$share->getHideDownload()) {
\OCP\Util::addScript('files_sharing', 'public_note');

$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
// TRANSLATORS The placeholder refers to the software product name as in 'Add to your Nextcloud'
$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your %s', [$this->defaults->getProductName()]), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);

$responseComposer = [];

if ($shareIsFolder) {
$responseComposer[] = $downloadAllWhite;
$responseComposer[] = $downloadAll;
} else {
$responseComposer[] = $downloadWhite;
$responseComposer[] = $download;
}
$responseComposer[] = $directLink;
if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
$responseComposer[] = $externalShare;
}

$response->setHeaderActions($responseComposer);
}

$response->setContentSecurityPolicy($csp);

$this->emitAccessShareHook($share);
$this->emitShareAccessEvent($share, self::SHARE_ACCESS);
Expand Down
Loading