Skip to content

Commit

Permalink
Changes required to allow third-party Nextcloud application to use mu…
Browse files Browse the repository at this point in the history
…ltiple requests per process approach for document previews and gallery previews

Signed-off-by: Tomasz Grobelny <[email protected]>
  • Loading branch information
tomasz-grobelny committed Apr 3, 2019
1 parent 0f2490d commit 6451274
Show file tree
Hide file tree
Showing 14 changed files with 118 additions and 69 deletions.
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
'OCP\\AppFramework\\Db\\MultipleObjectsReturnedException' => $baseDir . '/lib/public/AppFramework/Db/MultipleObjectsReturnedException.php',
'OCP\\AppFramework\\Db\\QBMapper' => $baseDir . '/lib/public/AppFramework/Db/QBMapper.php',
'OCP\\AppFramework\\Http' => $baseDir . '/lib/public/AppFramework/Http.php',
'OCP\\AppFramework\\HttpContext' => $baseDir . '/lib/public/AppFramework/HttpContext.php',
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => $baseDir . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
'OCP\\AppFramework\\Http\\DataDisplayResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
'OCP\\AppFramework\\Http\\DataDownloadResponse' => $baseDir . '/lib/public/AppFramework/Http/DataDownloadResponse.php',
Expand Down
1 change: 1 addition & 0 deletions lib/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\AppFramework\\Db\\MultipleObjectsReturnedException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/MultipleObjectsReturnedException.php',
'OCP\\AppFramework\\Db\\QBMapper' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Db/QBMapper.php',
'OCP\\AppFramework\\Http' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http.php',
'OCP\\AppFramework\\HttpContext' => __DIR__ . '/../../..' . '/lib/public/AppFramework/HttpContext.php',
'OCP\\AppFramework\\Http\\ContentSecurityPolicy' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/ContentSecurityPolicy.php',
'OCP\\AppFramework\\Http\\DataDisplayResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDisplayResponse.php',
'OCP\\AppFramework\\Http\\DataDownloadResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/DataDownloadResponse.php',
Expand Down
3 changes: 1 addition & 2 deletions lib/private/AppFramework/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ public static function main(string $controllerName, string $methodName, DIContai
$responseCookies,
$output,
$response
) = $dispatcher->dispatch($controller, $methodName);

) = $dispatcher->dispatch($controller, $methodName, $container->query(IRequest::class));
$io = $container[IOutput::class];

if(!is_null($httpHeaders)) {
Expand Down
12 changes: 2 additions & 10 deletions lib/private/AppFramework/DependencyInjection/DIContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,12 @@ public function __construct($appName, $urlParams = array(), ServerContainer $ser
// aliases
$this->registerAlias('appName', 'AppName');
$this->registerAlias('webRoot', 'WebRoot');
$this->registerAlias('userId', 'UserId');

/**
* Core services
*/
$this->registerService(IOutput::class, function(){
return new Output($this->getServer()->getWebRoot());
return $this->getServer()->query(IOutput::class);
});

$this->registerService(Folder::class, function() {
Expand Down Expand Up @@ -138,11 +137,6 @@ public function __construct($appName, $urlParams = array(), ServerContainer $ser
return $c;
});

// commonly used attributes
$this->registerService('UserId', function ($c) {
return $c->query(IUserSession::class)->getSession()->get('user_id');
});

$this->registerService('WebRoot', function ($c) {
return $c->query('ServerContainer')->getWebRoot();
});
Expand All @@ -166,8 +160,7 @@ public function __construct($appName, $urlParams = array(), ServerContainer $ser
return new Dispatcher(
$c['Protocol'],
$c['MiddlewareDispatcher'],
$c->query(IControllerMethodReflector::class),
$c['Request']
$c->query(IControllerMethodReflector::class)
);
});

Expand All @@ -191,7 +184,6 @@ public function __construct($appName, $urlParams = array(), ServerContainer $ser

$dispatcher->registerMiddleware(
new OC\AppFramework\Middleware\Security\SameSiteCookieMiddleware(
$c->query(IRequest::class),
$c->query(IControllerMethodReflector::class)
)
);
Expand Down
28 changes: 13 additions & 15 deletions lib/private/AppFramework/Http/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\HttpContext;
use OCP\IRequest;


Expand All @@ -54,25 +55,19 @@ class Dispatcher {
/** @var ControllerMethodReflector */
private $reflector;

/** @var IRequest */
private $request;

/**
* @param Http $protocol the http protocol with contains all status headers
* @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
* runs the middleware
* @param ControllerMethodReflector $reflector the reflector that is used to inject
* the arguments for the controller
* @param IRequest $request the incoming request
*/
public function __construct(Http $protocol,
MiddlewareDispatcher $middlewareDispatcher,
ControllerMethodReflector $reflector,
IRequest $request) {
ControllerMethodReflector $reflector) {
$this->protocol = $protocol;
$this->middlewareDispatcher = $middlewareDispatcher;
$this->reflector = $reflector;
$this->request = $request;
}


Expand All @@ -86,17 +81,20 @@ public function __construct(Http $protocol,
* the response output
* @throws \Exception
*/
public function dispatch(Controller $controller, string $methodName): array {
public function dispatch(Controller $controller, string $methodName, IRequest $request): array {
$out = [null, [], null];

try {
// prefill reflector with everything thats needed for the
// middlewares
$this->reflector->reflect($controller, $methodName);

$context = new HttpContext();
$context->request = $request;
$this->middlewareDispatcher->setContext($context);
$this->middlewareDispatcher->beforeController($controller,
$methodName);
$response = $this->executeController($controller, $methodName);
$response = $this->executeController($controller, $methodName, $request);

// if an exception appears, the middleware checks if it can handle the
// exception and creates a response. If no response is created, it is
Expand Down Expand Up @@ -131,7 +129,7 @@ public function dispatch(Controller $controller, string $methodName): array {
* @param string $methodName the method on the controller that should be executed
* @return Response
*/
private function executeController(Controller $controller, string $methodName): Response {
private function executeController(Controller $controller, string $methodName, IRequest $request): Response {
$arguments = [];

// valid types that will be casted
Expand All @@ -141,16 +139,16 @@ private function executeController(Controller $controller, string $methodName):

// try to get the parameter from the request object and cast
// it to the type annotated in the @param annotation
$value = $this->request->getParam($param, $default);
$value = $request->getParam($param, $default);
$type = $this->reflector->getType($param);

// if this is submitted using GET or a POST form, 'false' should be
// converted to false
if(($type === 'bool' || $type === 'boolean') &&
$value === 'false' &&
(
$this->request->method === 'GET' ||
strpos($this->request->getHeader('Content-Type'),
$request->method === 'GET' ||
strpos($request->getHeader('Content-Type'),
'application/x-www-form-urlencoded') !== false
)
) {
Expand All @@ -169,11 +167,11 @@ private function executeController(Controller $controller, string $methodName):
if($response instanceof DataResponse || !($response instanceof Response)) {

// get format from the url format or request format parameter
$format = $this->request->getParam('format');
$format = $request->getParam('format');

// if none is given try the first Accept header
if($format === null) {
$headers = $this->request->getHeader('Accept');
$headers = $request->getHeader('Accept');
$format = $controller->getResponderByHTTPHeader($headers, null);
}

Expand Down
8 changes: 8 additions & 0 deletions lib/private/AppFramework/Middleware/MiddlewareDispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\HttpContext;

/**
* This class is used to store and run all the middleware in correct order
Expand Down Expand Up @@ -76,6 +77,13 @@ public function getMiddlewares(): array {
return $this->middlewares;
}

public function setContext(HttpContext $context){
$middlewareCount = \count($this->middlewares);
for($i = 0; $i < $middlewareCount; $i++){
$middleware = $this->middlewares[$i];
$middleware->setContext($context);
}
}

/**
* This is being run in normal order before the controller is being
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,23 @@

use OC\AppFramework\Http\Request;
use OC\AppFramework\Middleware\Security\Exceptions\LaxSameSiteCookieFailedException;
use OC\AppFramework\Utility\ControllerMethodReflector;
use OCP\AppFramework\Utility\IControllerMethodReflector;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Middleware;
use OCP\IRequest;

class SameSiteCookieMiddleware extends Middleware {

/** @var Request */
private $request;

/** @var ControllerMethodReflector */
/** @var IControllerMethodReflector */
private $reflector;

public function __construct(Request $request,
ControllerMethodReflector $reflector) {
$this->request = $request;
public function __construct(IControllerMethodReflector $reflector) {
$this->reflector = $reflector;
}

public function beforeController($controller, $methodName) {
$requestUri = $this->request->getScriptName();
$requestUri = $this->context->request->getScriptName();
$processingScript = explode('/', $requestUri);
$processingScript = $processingScript[count($processingScript)-1];

Expand All @@ -57,7 +53,7 @@ public function beforeController($controller, $methodName) {
return;
}

if (!$this->request->passesLaxCookieCheck()) {
if (!$this->context->request->passesLaxCookieCheck()) {
throw new LaxSameSiteCookieFailedException();
}
}
Expand All @@ -66,7 +62,7 @@ public function afterException($controller, $methodName, \Exception $exception)
if ($exception instanceof LaxSameSiteCookieFailedException) {
$respone = new Response();
$respone->setStatus(Http::STATUS_FOUND);
$respone->addHeader('Location', $this->request->getRequestUri());
$respone->addHeader('Location', $this->context->request->getRequestUri());

$this->setSameSiteCookie();

Expand All @@ -77,7 +73,7 @@ public function afterException($controller, $methodName, \Exception $exception)
}

protected function setSameSiteCookie() {
$cookieParams = $this->request->getCookieParams();
$cookieParams = $this->context->request->getCookieParams();
$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
$policies = [
'lax',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class ControllerMethodReflector implements IControllerMethodReflector {
* @param string $method the method which we want to inspect
*/
public function reflect($object, string $method){
$this->annotations = [];
$this->types = [];
$this->parameters = [];

$reflection = new \ReflectionMethod($object, $method);
$docs = $reflection->getDocComment();

Expand Down
16 changes: 13 additions & 3 deletions lib/private/AppFramework/Utility/SimpleContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,23 @@ public function query($name) {
return $this->offsetGet($name);
} else {
$object = $this->resolve($name);
$this->registerService($name, function () use ($object) {
return $object;
});
if (!$this->endsWith($name, 'Controller')) {
$this->registerService($name, function () use ($object) {
return $object;
});
}
return $object;
}
}

private function endsWith($haystack, $needle) {
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $needle);
}

/**
* @param string $name
* @param mixed $value
Expand Down
8 changes: 8 additions & 0 deletions lib/private/Files/Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ class Filesystem {
/** @var bool */
private static $logWarningWhenAddingStorageWrapper = true;

public static function reset() {
self::$loaded = false;
self::$defaultInstance = null;
self::$usersSetup = array();
self::$normalizedPathCache = null;
self::$listeningForProviders = false;
}

/**
* @param bool $shouldLog
* @return bool previous value
Expand Down
30 changes: 12 additions & 18 deletions lib/private/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

namespace OC;

use OCP\AppFramework\Http\IOutput;
use bantu\IniGetWrapper\IniGetWrapper;
use OC\Accounts\AccountManager;
use OC\App\AppManager;
Expand All @@ -56,6 +57,7 @@
use OC\AppFramework\Http\Request;
use OC\AppFramework\Utility\SimpleContainer;
use OC\AppFramework\Utility\TimeFactory;
use OC\AppFramework\Http\Output;
use OC\Authentication\LoginCredentials\Store;
use OC\Authentication\Token\IProvider;
use OC\Avatar\AvatarManager;
Expand Down Expand Up @@ -161,6 +163,7 @@
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use OCP\IUserSession;

/**
* Class Server
Expand All @@ -184,6 +187,11 @@ public function __construct($webRoot, \OC\Config $config) {
// To find out if we are running from CLI or not
$this->registerParameter('isCLI', \OC::$CLI);

$this->registerService('UserId', function ($c) {
return $c->query(IUserSession::class)->getSession()->get('user_id');
});
$this->registerAlias('userId', 'UserId');

$this->registerService(\OCP\IServerContainer::class, function (IServerContainer $c) {
return $c;
});
Expand Down Expand Up @@ -996,30 +1004,16 @@ public function __construct($webRoot, \OC\Config $config) {
$this->registerAlias(EventDispatcherInterface::class, EventDispatcher::class);

$this->registerService('CryptoWrapper', function (Server $c) {
// FIXME: Instantiiated here due to cyclic dependency
$request = new Request(
[
'get' => $_GET,
'post' => $_POST,
'files' => $_FILES,
'server' => $_SERVER,
'env' => $_ENV,
'cookies' => $_COOKIE,
'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
? $_SERVER['REQUEST_METHOD']
: null,
],
$c->getSecureRandom(),
$c->getConfig()
);

return new CryptoWrapper(
$c->getConfig(),
$c->getCrypto(),
$c->getSecureRandom(),
$request
$c->getRequest()
);
});
$this->registerService(IOutput::class, function(Server $c) {
return new Output($c->getWebRoot());
});
$this->registerService('CsrfTokenManager', function (Server $c) {
$tokenGenerator = new CsrfTokenGenerator($c->getSecureRandom());

Expand Down
Loading

0 comments on commit 6451274

Please sign in to comment.