Skip to content
Closed
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
155 changes: 155 additions & 0 deletions apps/dav/appinfo/v2/publicremote.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Bjoern Schiessle <[email protected]>
* @author Björn Schießle <[email protected]>
* @author Christoph Wurst <[email protected]>
* @author Joas Schilling <[email protected]>
* @author Julius Härtl <[email protected]>
* @author Lukas Reschke <[email protected]>
* @author Morris Jobke <[email protected]>
* @author Robin Appelman <[email protected]>
* @author Roeland Jago Douma <[email protected]>
* @author Thomas Müller <[email protected]>
* @author Vincent Petry <[email protected]>
*
* @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/>
*
*/

use OC\Files\Filesystem;
use OC\Files\Storage\Wrapper\PermissionsMask;
use OC\Files\View;
use OCA\DAV\Storage\PublicOwnerWrapper;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Mount\IMountManager;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IPreview;
use OCP\IRequest;
use OCP\ISession;
use OCP\ITagManager;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Security\Bruteforce\IThrottler;
use OCP\Share\IManager;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Exception\NotAuthenticated;
use Sabre\DAV\Exception\NotFound;

// load needed apps
$RUNTIME_APPTYPES = ['filesystem', 'authentication', 'logging'];
OC_App::loadApps($RUNTIME_APPTYPES);
OC_Util::obEnd();

$session = \OCP\Server::get(ISession::class);
$request = \OCP\Server::get(IRequest::class);

$session->close();
$requestUri = $request->getRequestUri();

// Backends
$authBackend = new OCA\DAV\Connector\Sabre\PublicAuth(

Check failure

Code scanning / Psalm

UndefinedClass

Class, interface or enum named OCA\DAV\Connector\Sabre\PublicAuth does not exist
$request,
\OCP\Server::get(IManager::class),
$session,
\OCP\Server::get(IThrottler::class),
\OCP\Server::get(LoggerInterface::class)
);
$authPlugin = new \Sabre\DAV\Auth\Plugin($authBackend);

$l10nFactory = \OCP\Server::get(IFactory::class);
$serverFactory = new OCA\DAV\Connector\Sabre\ServerFactory(
\OCP\Server::get(IConfig::class),
\OCP\Server::get(LoggerInterface::class),
\OCP\Server::get(IDBConnection::class),
\OCP\Server::get(IUserSession::class),
\OCP\Server::get(IMountManager::class),
\OCP\Server::get(ITagManager::class),
$request,
\OCP\Server::get(IPreview::class),
\OCP\Server::get(IEventDispatcher::class),
$l10nFactory->get('dav'),
);


$linkCheckPlugin = new \OCA\DAV\Files\Sharing\PublicLinkCheckPlugin();
$filesDropPlugin = new \OCA\DAV\Files\Sharing\FilesDropPlugin();

// Define root url with /public.php/dav/files/TOKEN
/** @var string $baseuri defined in public.php */
preg_match('/(^files\/\w+)/i', substr($requestUri, strlen($baseuri)), $match);
$baseuri = $baseuri . $match[0];

$server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, function (\Sabre\DAV\Server $server) use ($authBackend, $linkCheckPlugin, $filesDropPlugin) {
$isAjax = in_array('XMLHttpRequest', explode(',', $_SERVER['HTTP_X_REQUESTED_WITH'] ?? ''));
$federatedShareProvider = \OCP\Server::get(FederatedShareProvider::class);
if ($federatedShareProvider->isOutgoingServer2serverShareEnabled() === false && !$isAjax) {
// this is what is thrown when trying to access a non-existing share
throw new NotAuthenticated();
}

$share = $authBackend->getShare();

Check failure

Code scanning / Psalm

UndefinedInterfaceMethod

Method Sabre\DAV\Auth\Backend\BackendInterface::getShare does not exist
$owner = $share->getShareOwner();
$isReadable = $share->getPermissions() & \OCP\Constants::PERMISSION_READ;
$fileId = $share->getNodeId();

// FIXME: should not add storage wrappers outside of preSetup, need to find a better way
/** @psalm-suppress InternalMethod */
$previousLog = Filesystem::logWarningWhenAddingStorageWrapper(false);

/** @psalm-suppress MissingClosureParamType */
Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($share) {
return new PermissionsMask(['storage' => $storage, 'mask' => $share->getPermissions() | \OCP\Constants::PERMISSION_SHARE]);
});

/** @psalm-suppress MissingClosureParamType */
Filesystem::addStorageWrapper('shareOwner', function ($mountPoint, $storage) use ($share) {
return new PublicOwnerWrapper(['storage' => $storage, 'owner' => $share->getShareOwner()]);
});

/** @psalm-suppress InternalMethod */
Filesystem::logWarningWhenAddingStorageWrapper($previousLog);

OC_Util::tearDownFS();
OC_Util::setupFS($owner);
$ownerView = new View('/'. $owner . '/files');
$path = $ownerView->getPath($fileId);
$fileInfo = $ownerView->getFileInfo($path);

if ($fileInfo === false) {
throw new NotFound();
}

$linkCheckPlugin->setFileInfo($fileInfo);

// If not readble (files_drop) enable the filesdrop plugin
if (!$isReadable) {
$filesDropPlugin->enable();
}

$view = new View($ownerView->getAbsolutePath($path));
$filesDropPlugin->setView($view);

return $view;
});

$server->addPlugin($linkCheckPlugin);
$server->addPlugin($filesDropPlugin);

// And off we go!
$server->exec();
66 changes: 43 additions & 23 deletions public.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,55 @@
*/
require_once __DIR__ . '/lib/versioncheck.php';

use Psr\Log\LoggerInterface;

/**
* @param $service
* @return string
*/
function resolveService(string $service): string {
$services = [
'webdav' => 'dav/appinfo/v1/publicwebdav.php',
'dav' => 'dav/appinfo/v2/publicremote.php',
];
if (isset($services[$service])) {
return $services[$service];
}

return \OC::$server->getConfig()->getAppValue('core', 'remote_' . $service);
}

try {
require_once __DIR__ . '/lib/base.php';

// All resources served via the DAV endpoint should have the strictest possible
// policy. Exempted from this is the SabreDAV browser plugin which overwrites
// this policy with a softer one if debug mode is enabled.
header("Content-Security-Policy: default-src 'none';");

if (\OCP\Util::needUpgrade()) {
// since the behavior of apps or remotes are unpredictable during
// an upgrade, return a 503 directly
OC_Template::printErrorPage('Service unavailable', '', 503);
exit;
throw new RemoteException('Service unavailable', 503);
}

OC::checkMaintenanceMode(\OC::$server->get(\OC\SystemConfig::class));
$request = \OC::$server->getRequest();
$pathInfo = $request->getPathInfo();

if (!$pathInfo && $request->getParam('service', '') === '') {
http_response_code(404);
exit;
} elseif ($request->getParam('service', '')) {
$service = $request->getParam('service', '');
} else {
$pathInfo = trim($pathInfo, '/');
[$service] = explode('/', $pathInfo);
if ($pathInfo === false || $pathInfo === '') {
throw new RemoteException('Path not found', 404);
}
$file = \OC::$server->getConfig()->getAppValue('core', 'public_' . strip_tags($service));
if ($file === '') {
http_response_code(404);
exit;
if (!$pos = strpos($pathInfo, '/', 1)) {
$pos = strlen($pathInfo);
}
$service = substr($pathInfo, 1, $pos - 1);

$file = resolveService($service);

if (!$file) {
throw new RemoteException('Path not found', 404);
}

$file = ltrim($file, '/');

$parts = explode('/', $file, 2);
$app = $parts[0];
Expand All @@ -70,25 +92,23 @@
OC_App::loadApps(['filesystem', 'logging']);

if (!\OC::$server->getAppManager()->isInstalled($app)) {
http_response_code(404);
exit;
throw new RemoteException('App not installed: ' . $app);
}
OC_App::loadApp($app);
OC_User::setIncognitoMode(true);

$baseuri = OC::$WEBROOT . '/public.php/' . $service . '/';

require_once OC_App::getAppPath($app) . '/' . $parts[1];
$baseuri = OC::$WEBROOT . '/public.php/'.$service.'/';
require_once $file;
} catch (Exception $ex) {
$status = 500;
if ($ex instanceof \OC\ServiceUnavailableException) {
$status = 503;
}
//show the user a detailed error page
\OC::$server->getLogger()->logException($ex, ['app' => 'public']);
\OCP\Server::get(LoggerInterface::class)->error($ex->getMessage(), ['app' => 'public', 'exception' => $ex]);
OC_Template::printExceptionErrorPage($ex, $status);
} catch (Error $ex) {
//show the user a detailed error page
\OC::$server->getLogger()->logException($ex, ['app' => 'public']);
\OCP\Server::get(LoggerInterface::class)->error($ex->getMessage(), ['app' => 'public', 'exception' => $ex]);
OC_Template::printExceptionErrorPage($ex, 500);
}