aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/dav/lib/DAV/Server.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sabre/dav/lib/DAV/Server.php')
-rw-r--r--vendor/sabre/dav/lib/DAV/Server.php694
1 files changed, 337 insertions, 357 deletions
diff --git a/vendor/sabre/dav/lib/DAV/Server.php b/vendor/sabre/dav/lib/DAV/Server.php
index f7fcf3057..09760e9d1 100644
--- a/vendor/sabre/dav/lib/DAV/Server.php
+++ b/vendor/sabre/dav/lib/DAV/Server.php
@@ -1,76 +1,79 @@
<?php
+declare(strict_types=1);
+
namespace Sabre\DAV;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
-use Sabre\Event\EventEmitter;
+use Sabre\Event\EmitterInterface;
+use Sabre\Event\WildcardEmitterTrait;
use Sabre\HTTP;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
-use Sabre\HTTP\URLUtil;
use Sabre\Uri;
/**
- * Main DAV server class
+ * Main DAV server class.
*
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
-class Server extends EventEmitter implements LoggerAwareInterface {
-
+class Server implements LoggerAwareInterface, EmitterInterface
+{
+ use WildcardEmitterTrait;
use LoggerAwareTrait;
/**
- * Infinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree
+ * Infinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree.
*/
const DEPTH_INFINITY = -1;
/**
- * XML namespace for all SabreDAV related elements
+ * XML namespace for all SabreDAV related elements.
*/
const NS_SABREDAV = 'http://sabredav.org/ns';
/**
- * The tree object
+ * The tree object.
*
* @var Tree
*/
public $tree;
/**
- * The base uri
+ * The base uri.
*
* @var string
*/
protected $baseUri = null;
/**
- * httpResponse
+ * httpResponse.
*
* @var HTTP\Response
*/
public $httpResponse;
/**
- * httpRequest
+ * httpRequest.
*
* @var HTTP\Request
*/
public $httpRequest;
/**
- * PHP HTTP Sapi
+ * PHP HTTP Sapi.
*
* @var HTTP\Sapi
*/
public $sapi;
/**
- * The list of plugins
+ * The list of plugins.
*
* @var array
*/
@@ -98,7 +101,6 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* @var string[]
*/
public $protectedProperties = [
-
// RFC4918
'{DAV:}getcontentlength',
'{DAV:}getetag',
@@ -129,12 +131,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
// sabredav extensions
'{http://sabredav.org/ns}sync-token',
-
];
/**
* This is a flag that allow or not showing file, line and code
- * of the exception in the returned XML
+ * of the exception in the returned XML.
*
* @var bool
*/
@@ -181,10 +182,10 @@ class Server extends EventEmitter implements LoggerAwareInterface {
*
* @var bool
*/
- static $exposeVersion = true;
+ public static $exposeVersion = true;
/**
- * Sets up the server
+ * Sets up the server.
*
* If a Sabre\DAV\Tree object is passed as an argument, it will
* use it as the directory tree. If a Sabre\DAV\INode is passed, it
@@ -198,25 +199,15 @@ class Server extends EventEmitter implements LoggerAwareInterface {
*
* @param Tree|INode|array|null $treeOrNode The tree object
*/
- function __construct($treeOrNode = null) {
-
+ public function __construct($treeOrNode = null)
+ {
if ($treeOrNode instanceof Tree) {
$this->tree = $treeOrNode;
} elseif ($treeOrNode instanceof INode) {
$this->tree = new Tree($treeOrNode);
} elseif (is_array($treeOrNode)) {
-
- // If it's an array, a list of nodes was passed, and we need to
- // create the root node.
- foreach ($treeOrNode as $node) {
- if (!($node instanceof INode)) {
- throw new Exception('Invalid argument passed to constructor. If you\'re passing an array, all the values must implement Sabre\\DAV\\INode');
- }
- }
-
$root = new SimpleCollection('root', $treeOrNode);
$this->tree = new Tree($root);
-
} elseif (is_null($treeOrNode)) {
$root = new SimpleCollection('root');
$this->tree = new Tree($root);
@@ -229,18 +220,14 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$this->httpResponse = new HTTP\Response();
$this->httpRequest = $this->sapi->getRequest();
$this->addPlugin(new CorePlugin());
-
}
/**
- * Starts the DAV Server
- *
- * @return void
+ * Starts the DAV Server.
*/
- function exec() {
-
+ public function start()
+ {
try {
-
// If nginx (pre-1.2) is used as a proxy server, and SabreDAV as an
// origin, we must make sure we send back HTTP/1.0 if this was
// requested.
@@ -252,9 +239,7 @@ class Server extends EventEmitter implements LoggerAwareInterface {
// Setting the base url
$this->httpRequest->setBaseUrl($this->getBaseUri());
$this->invokeMethod($this->httpRequest, $this->httpResponse);
-
- } catch (\Exception $e) {
-
+ } catch (\Throwable $e) {
try {
$this->emit('exception', [$e]);
} catch (\Exception $ignore) {
@@ -266,10 +251,8 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$error->setAttribute('xmlns:s', self::NS_SABREDAV);
$DOM->appendChild($error);
- $h = function($v) {
-
- return htmlspecialchars($v, ENT_NOQUOTES, 'UTF-8');
-
+ $h = function ($v) {
+ return htmlspecialchars((string) $v, ENT_NOQUOTES, 'UTF-8');
};
if (self::$exposeVersion) {
@@ -299,18 +282,13 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
}
-
if ($e instanceof Exception) {
-
$httpCode = $e->getHTTPCode();
$e->serialize($this, $error);
$headers = $e->getHTTPHeaders($this);
-
} else {
-
$httpCode = 500;
$headers = [];
-
}
$headers['Content-Type'] = 'application/xml; charset=utf-8';
@@ -318,37 +296,46 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$this->httpResponse->setHeaders($headers);
$this->httpResponse->setBody($DOM->saveXML());
$this->sapi->sendResponse($this->httpResponse);
-
}
+ }
+ /**
+ * Alias of start().
+ *
+ * @deprecated
+ */
+ public function exec()
+ {
+ $this->start();
}
/**
- * Sets the base server uri
+ * Sets the base server uri.
*
* @param string $uri
- * @return void
*/
- function setBaseUri($uri) {
-
+ public function setBaseUri($uri)
+ {
// If the baseUri does not end with a slash, we must add it
- if ($uri[strlen($uri) - 1] !== '/')
+ if ('/' !== $uri[strlen($uri) - 1]) {
$uri .= '/';
+ }
$this->baseUri = $uri;
-
}
/**
- * Returns the base responding uri
+ * Returns the base responding uri.
*
* @return string
*/
- function getBaseUri() {
+ public function getBaseUri()
+ {
+ if (is_null($this->baseUri)) {
+ $this->baseUri = $this->guessBaseUri();
+ }
- if (is_null($this->baseUri)) $this->baseUri = $this->guessBaseUri();
return $this->baseUri;
-
}
/**
@@ -359,53 +346,50 @@ class Server extends EventEmitter implements LoggerAwareInterface {
*
* @return string
*/
- function guessBaseUri() {
-
+ public function guessBaseUri()
+ {
$pathInfo = $this->httpRequest->getRawServerValue('PATH_INFO');
$uri = $this->httpRequest->getRawServerValue('REQUEST_URI');
// If PATH_INFO is found, we can assume it's accurate.
if (!empty($pathInfo)) {
-
// We need to make sure we ignore the QUERY_STRING part
- if ($pos = strpos($uri, '?'))
+ if ($pos = strpos($uri, '?')) {
$uri = substr($uri, 0, $pos);
+ }
// PATH_INFO is only set for urls, such as: /example.php/path
// in that case PATH_INFO contains '/path'.
// Note that REQUEST_URI is percent encoded, while PATH_INFO is
// not, Therefore they are only comparable if we first decode
// REQUEST_INFO as well.
- $decodedUri = URLUtil::decodePath($uri);
+ $decodedUri = HTTP\decodePath($uri);
// A simple sanity check:
if (substr($decodedUri, strlen($decodedUri) - strlen($pathInfo)) === $pathInfo) {
$baseUri = substr($decodedUri, 0, strlen($decodedUri) - strlen($pathInfo));
- return rtrim($baseUri, '/') . '/';
- }
- throw new Exception('The REQUEST_URI (' . $uri . ') did not end with the contents of PATH_INFO (' . $pathInfo . '). This server might be misconfigured.');
+ return rtrim($baseUri, '/').'/';
+ }
+ throw new Exception('The REQUEST_URI ('.$uri.') did not end with the contents of PATH_INFO ('.$pathInfo.'). This server might be misconfigured.');
}
// The last fallback is that we're just going to assume the server root.
return '/';
-
}
/**
- * Adds a plugin to the server
+ * Adds a plugin to the server.
*
* For more information, console the documentation of Sabre\DAV\ServerPlugin
*
* @param ServerPlugin $plugin
- * @return void
*/
- function addPlugin(ServerPlugin $plugin) {
-
+ public function addPlugin(ServerPlugin $plugin)
+ {
$this->plugins[$plugin->getPluginName()] = $plugin;
$plugin->initialize($this);
-
}
/**
@@ -414,26 +398,26 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* This function returns null if the plugin was not found.
*
* @param string $name
+ *
* @return ServerPlugin
*/
- function getPlugin($name) {
-
- if (isset($this->plugins[$name]))
+ public function getPlugin($name)
+ {
+ if (isset($this->plugins[$name])) {
return $this->plugins[$name];
+ }
return null;
-
}
/**
- * Returns all plugins
+ * Returns all plugins.
*
* @return array
*/
- function getPlugins() {
-
+ public function getPlugins()
+ {
return $this->plugins;
-
}
/**
@@ -441,29 +425,29 @@ class Server extends EventEmitter implements LoggerAwareInterface {
*
* @return LoggerInterface
*/
- function getLogger() {
-
+ public function getLogger()
+ {
if (!$this->logger) {
$this->logger = new NullLogger();
}
- return $this->logger;
+ return $this->logger;
}
/**
- * Handles a http request, and execute a method based on its name
+ * Handles a http request, and execute a method based on its name.
*
- * @param RequestInterface $request
+ * @param RequestInterface $request
* @param ResponseInterface $response
- * @param bool $sendResponse Whether to send the HTTP response to the DAV client.
- * @return void
+ * @param bool $sendResponse whether to send the HTTP response to the DAV client
*/
- function invokeMethod(RequestInterface $request, ResponseInterface $response, $sendResponse = true) {
-
+ public function invokeMethod(RequestInterface $request, ResponseInterface $response, $sendResponse = true)
+ {
$method = $request->getMethod();
- if (!$this->emit('beforeMethod:' . $method, [$request, $response])) return;
- if (!$this->emit('beforeMethod', [$request, $response])) return;
+ if (!$this->emit('beforeMethod:'.$method, [$request, $response])) {
+ return;
+ }
if (self::$exposeVersion) {
$response->setHeader('X-Sabre-Version', Version::VERSION);
@@ -473,32 +457,31 @@ class Server extends EventEmitter implements LoggerAwareInterface {
if (!$this->checkPreconditions($request, $response)) {
$this->sapi->sendResponse($response);
+
return;
}
- if ($this->emit('method:' . $method, [$request, $response])) {
- if ($this->emit('method', [$request, $response])) {
- $exMessage = "There was no plugin in the system that was willing to handle this " . $method . " method.";
- if ($method === "GET") {
- $exMessage .= " Enable the Browser plugin to get a better result here.";
- }
-
- // Unsupported method
- throw new Exception\NotImplemented($exMessage);
+ if ($this->emit('method:'.$method, [$request, $response])) {
+ $exMessage = 'There was no plugin in the system that was willing to handle this '.$method.' method.';
+ if ('GET' === $method) {
+ $exMessage .= ' Enable the Browser plugin to get a better result here.';
}
+
+ // Unsupported method
+ throw new Exception\NotImplemented($exMessage);
}
- if (!$this->emit('afterMethod:' . $method, [$request, $response])) return;
- if (!$this->emit('afterMethod', [$request, $response])) return;
+ if (!$this->emit('afterMethod:'.$method, [$request, $response])) {
+ return;
+ }
- if ($response->getStatus() === null) {
+ if (null === $response->getStatus()) {
throw new Exception('No subsystem set a valid HTTP status code. Something must have interrupted the request without providing further detail.');
}
if ($sendResponse) {
$this->sapi->sendResponse($response);
$this->emit('afterResponse', [$request, $response]);
}
-
}
// {{{ HTTP/WebDAV protocol helpers
@@ -507,10 +490,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* Returns an array with all the supported HTTP methods for a specific uri.
*
* @param string $path
+ *
* @return array
*/
- function getAllowedMethods($path) {
-
+ public function getAllowedMethods($path)
+ {
$methods = [
'OPTIONS',
'GET',
@@ -521,7 +505,7 @@ class Server extends EventEmitter implements LoggerAwareInterface {
'PROPPATCH',
'COPY',
'MOVE',
- 'REPORT'
+ 'REPORT',
];
// The MKCOL is only allowed on an unmapped uri
@@ -532,22 +516,22 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
// We're also checking if any of the plugins register any new methods
- foreach ($this->plugins as $plugin) $methods = array_merge($methods, $plugin->getHTTPMethods($path));
+ foreach ($this->plugins as $plugin) {
+ $methods = array_merge($methods, $plugin->getHTTPMethods($path));
+ }
array_unique($methods);
return $methods;
-
}
/**
- * Gets the uri for the request, keeping the base uri into consideration
+ * Gets the uri for the request, keeping the base uri into consideration.
*
* @return string
*/
- function getRequestUri() {
-
+ public function getRequestUri()
+ {
return $this->calculateUri($this->httpRequest->getUrl());
-
}
/**
@@ -559,66 +543,65 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* * uri-decodes the path
*
* @param string $uri
+ *
* @throws Exception\Forbidden A permission denied exception is thrown whenever there was an attempt to supply a uri outside of the base uri
+ *
* @return string
*/
- function calculateUri($uri) {
-
- if ($uri[0] != '/' && strpos($uri, '://')) {
-
+ public function calculateUri($uri)
+ {
+ if ('' != $uri && '/' != $uri[0] && strpos($uri, '://')) {
$uri = parse_url($uri, PHP_URL_PATH);
-
}
- $uri = Uri\normalize(str_replace('//', '/', $uri));
+ $uri = Uri\normalize(preg_replace('|/+|', '/', $uri));
$baseUri = Uri\normalize($this->getBaseUri());
- if (strpos($uri, $baseUri) === 0) {
-
- return trim(URLUtil::decodePath(substr($uri, strlen($baseUri))), '/');
+ if (0 === strpos($uri, $baseUri)) {
+ return trim(HTTP\decodePath(substr($uri, strlen($baseUri))), '/');
// A special case, if the baseUri was accessed without a trailing
// slash, we'll accept it as well.
- } elseif ($uri . '/' === $baseUri) {
-
+ } elseif ($uri.'/' === $baseUri) {
return '';
-
} else {
-
- throw new Exception\Forbidden('Requested uri (' . $uri . ') is out of base uri (' . $this->getBaseUri() . ')');
-
+ throw new Exception\Forbidden('Requested uri ('.$uri.') is out of base uri ('.$this->getBaseUri().')');
}
-
}
/**
- * Returns the HTTP depth header
+ * Returns the HTTP depth header.
*
* This method returns the contents of the HTTP depth request header. If the depth header was 'infinity' it will return the Sabre\DAV\Server::DEPTH_INFINITY object
* It is possible to supply a default depth value, which is used when the depth header has invalid content, or is completely non-existent
*
* @param mixed $default
+ *
* @return int
*/
- function getHTTPDepth($default = self::DEPTH_INFINITY) {
-
+ public function getHTTPDepth($default = self::DEPTH_INFINITY)
+ {
// If its not set, we'll grab the default
$depth = $this->httpRequest->getHeader('Depth');
- if (is_null($depth)) return $default;
-
- if ($depth == 'infinity') return self::DEPTH_INFINITY;
+ if (is_null($depth)) {
+ return $default;
+ }
+ if ('infinity' == $depth) {
+ return self::DEPTH_INFINITY;
+ }
// If its an unknown value. we'll grab the default
- if (!ctype_digit($depth)) return $default;
-
- return (int)$depth;
+ if (!ctype_digit($depth)) {
+ return $default;
+ }
+ return (int) $depth;
}
/**
- * Returns the HTTP range header
+ * Returns the HTTP range header.
*
* This method returns null if there is no well-formed HTTP range request
* header or array($start, $end).
@@ -629,24 +612,29 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* If the second offset is null, it should be treated as the offset of the last byte of the entity
* If the first offset is null, the second offset should be used to retrieve the last x bytes of the entity
*
- * @return array|null
+ * @return int[]|null
*/
- function getHTTPRange() {
-
+ public function getHTTPRange()
+ {
$range = $this->httpRequest->getHeader('range');
- if (is_null($range)) return null;
+ if (is_null($range)) {
+ return null;
+ }
// Matching "Range: bytes=1234-5678: both numbers are optional
- if (!preg_match('/^bytes=([0-9]*)-([0-9]*)$/i', $range, $matches)) return null;
+ if (!preg_match('/^bytes=([0-9]*)-([0-9]*)$/i', $range, $matches)) {
+ return null;
+ }
- if ($matches[1] === '' && $matches[2] === '') return null;
+ if ('' === $matches[1] && '' === $matches[2]) {
+ return null;
+ }
return [
- $matches[1] !== '' ? $matches[1] : null,
- $matches[2] !== '' ? $matches[2] : null,
+ '' !== $matches[1] ? (int) $matches[1] : null,
+ '' !== $matches[2] ? (int) $matches[2] : null,
];
-
}
/**
@@ -675,8 +663,8 @@ class Server extends EventEmitter implements LoggerAwareInterface {
*
* @return array
*/
- function getHTTPPrefer() {
-
+ public function getHTTPPrefer()
+ {
$result = [
// can be true or false
'respond-async' => false,
@@ -689,23 +677,19 @@ class Server extends EventEmitter implements LoggerAwareInterface {
];
if ($prefer = $this->httpRequest->getHeader('Prefer')) {
-
$result = array_merge(
$result,
HTTP\parsePrefer($prefer)
);
-
- } elseif ($this->httpRequest->getHeader('Brief') == 't') {
+ } elseif ('t' == $this->httpRequest->getHeader('Brief')) {
$result['return'] = 'minimal';
}
return $result;
-
}
-
/**
- * Returns information about Copy and Move requests
+ * Returns information about Copy and Move requests.
*
* This function is created to help getting information about the source and the destination for the
* WebDAV MOVE and COPY HTTP request. It also validates a lot of information and throws proper exceptions
@@ -715,74 +699,82 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* * destinationExists - Whether or not the destination is an existing url (and should therefore be overwritten)
*
* @param RequestInterface $request
- * @throws Exception\BadRequest upon missing or broken request headers
+ *
+ * @throws Exception\BadRequest upon missing or broken request headers
* @throws Exception\UnsupportedMediaType when trying to copy into a
- * non-collection.
- * @throws Exception\PreconditionFailed If overwrite is set to false, but
- * the destination exists.
- * @throws Exception\Forbidden when source and destination paths are
- * identical.
- * @throws Exception\Conflict When trying to copy a node into its own
- * subtree.
+ * non-collection
+ * @throws Exception\PreconditionFailed if overwrite is set to false, but
+ * the destination exists
+ * @throws Exception\Forbidden when source and destination paths are
+ * identical
+ * @throws Exception\Conflict when trying to copy a node into its own
+ * subtree
+ *
* @return array
*/
- function getCopyAndMoveInfo(RequestInterface $request) {
-
+ public function getCopyAndMoveInfo(RequestInterface $request)
+ {
// Collecting the relevant HTTP headers
- if (!$request->getHeader('Destination')) throw new Exception\BadRequest('The destination header was not supplied');
+ if (!$request->getHeader('Destination')) {
+ throw new Exception\BadRequest('The destination header was not supplied');
+ }
$destination = $this->calculateUri($request->getHeader('Destination'));
$overwrite = $request->getHeader('Overwrite');
- if (!$overwrite) $overwrite = 'T';
- if (strtoupper($overwrite) == 'T') $overwrite = true;
- elseif (strtoupper($overwrite) == 'F') $overwrite = false;
+ if (!$overwrite) {
+ $overwrite = 'T';
+ }
+ if ('T' == strtoupper($overwrite)) {
+ $overwrite = true;
+ } elseif ('F' == strtoupper($overwrite)) {
+ $overwrite = false;
+ }
// We need to throw a bad request exception, if the header was invalid
- else throw new Exception\BadRequest('The HTTP Overwrite header should be either T or F');
-
- list($destinationDir) = URLUtil::splitPath($destination);
+ else {
+ throw new Exception\BadRequest('The HTTP Overwrite header should be either T or F');
+ }
+ list($destinationDir) = Uri\split($destination);
try {
$destinationParent = $this->tree->getNodeForPath($destinationDir);
- if (!($destinationParent instanceof ICollection)) throw new Exception\UnsupportedMediaType('The destination node is not a collection');
+ if (!($destinationParent instanceof ICollection)) {
+ throw new Exception\UnsupportedMediaType('The destination node is not a collection');
+ }
} catch (Exception\NotFound $e) {
-
// If the destination parent node is not found, we throw a 409
throw new Exception\Conflict('The destination node is not found');
}
try {
-
$destinationNode = $this->tree->getNodeForPath($destination);
// If this succeeded, it means the destination already exists
// we'll need to throw precondition failed in case overwrite is false
- if (!$overwrite) throw new Exception\PreconditionFailed('The destination node already exists, and the overwrite header is set to false', 'Overwrite');
-
+ if (!$overwrite) {
+ throw new Exception\PreconditionFailed('The destination node already exists, and the overwrite header is set to false', 'Overwrite');
+ }
} catch (Exception\NotFound $e) {
-
// Destination didn't exist, we're all good
$destinationNode = false;
-
}
$requestPath = $request->getPath();
if ($destination === $requestPath) {
throw new Exception\Forbidden('Source and destination uri are identical.');
}
- if (substr($destination, 0, strlen($requestPath) + 1) === $requestPath . '/') {
+ if (substr($destination, 0, strlen($requestPath) + 1) === $requestPath.'/') {
throw new Exception\Conflict('The destination may not be part of the same subtree as the source path.');
}
// These are the three relevant properties we need to return
return [
- 'destination' => $destination,
- 'destinationExists' => !!$destinationNode,
- 'destinationNode' => $destinationNode,
+ 'destination' => $destination,
+ 'destinationExists' => (bool) $destinationNode,
+ 'destinationNode' => $destinationNode,
];
-
}
/**
- * Returns a list of properties for a path
+ * Returns a list of properties for a path.
*
* This is a simplified version getPropertiesForPath. If you aren't
* interested in status codes, but you just want to have a flat list of
@@ -793,18 +785,18 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* returned.
*
* @param string $path
- * @param array $propertyNames
+ * @param array $propertyNames
+ *
* @return array
*/
- function getProperties($path, $propertyNames) {
-
+ public function getProperties($path, $propertyNames)
+ {
$result = $this->getPropertiesForPath($path, $propertyNames, 0);
if (isset($result[0][200])) {
return $result[0][200];
} else {
return [];
}
-
}
/**
@@ -816,26 +808,27 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* The parent node will not be returned.
*
* @param string $path
- * @param array $propertyNames
+ * @param array $propertyNames
+ *
* @return array
*/
- function getPropertiesForChildren($path, $propertyNames) {
-
+ public function getPropertiesForChildren($path, $propertyNames)
+ {
$result = [];
foreach ($this->getPropertiesForPath($path, $propertyNames, 1) as $k => $row) {
-
// Skipping the parent path
- if ($k === 0) continue;
+ if (0 === $k) {
+ continue;
+ }
$result[$row['href']] = $row[200];
-
}
- return $result;
+ return $result;
}
/**
- * Returns a list of HTTP headers for a particular resource
+ * Returns a list of HTTP headers for a particular resource.
*
* The generated http headers are based on properties provided by the
* resource. The method basically provides a simple mapping between
@@ -844,61 +837,64 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* The headers are intended to be used for HEAD and GET requests.
*
* @param string $path
+ *
* @return array
*/
- function getHTTPHeaders($path) {
-
+ public function getHTTPHeaders($path)
+ {
$propertyMap = [
- '{DAV:}getcontenttype' => 'Content-Type',
+ '{DAV:}getcontenttype' => 'Content-Type',
'{DAV:}getcontentlength' => 'Content-Length',
- '{DAV:}getlastmodified' => 'Last-Modified',
- '{DAV:}getetag' => 'ETag',
+ '{DAV:}getlastmodified' => 'Last-Modified',
+ '{DAV:}getetag' => 'ETag',
];
$properties = $this->getProperties($path, array_keys($propertyMap));
$headers = [];
foreach ($propertyMap as $property => $header) {
- if (!isset($properties[$property])) continue;
+ if (!isset($properties[$property])) {
+ continue;
+ }
if (is_scalar($properties[$property])) {
$headers[$header] = $properties[$property];
// GetLastModified gets special cased
} elseif ($properties[$property] instanceof Xml\Property\GetLastModified) {
- $headers[$header] = HTTP\Util::toHTTPDate($properties[$property]->getTime());
+ $headers[$header] = HTTP\toDate($properties[$property]->getTime());
}
-
}
return $headers;
-
}
/**
* Small helper to support PROPFIND with DEPTH_INFINITY.
*
* @param PropFind $propFind
- * @param array $yieldFirst
- * @return \Iterator
+ * @param array $yieldFirst
+ *
+ * @return \Traversable
*/
- private function generatePathNodes(PropFind $propFind, array $yieldFirst = null) {
- if ($yieldFirst !== null) {
+ private function generatePathNodes(PropFind $propFind, array $yieldFirst = null)
+ {
+ if (null !== $yieldFirst) {
yield $yieldFirst;
}
$newDepth = $propFind->getDepth();
$path = $propFind->getPath();
- if ($newDepth !== self::DEPTH_INFINITY) {
- $newDepth--;
+ if (self::DEPTH_INFINITY !== $newDepth) {
+ --$newDepth;
}
$propertyNames = $propFind->getRequestedProperties();
$propFindType = !empty($propertyNames) ? PropFind::NORMAL : PropFind::ALLPROPS;
foreach ($this->tree->getChildren($path) as $childNode) {
- if ($path !== '') {
- $subPath = $path . '/' . $childNode->getName();
+ if ('' !== $path) {
+ $subPath = $path.'/'.$childNode->getName();
} else {
$subPath = $childNode->getName();
}
@@ -906,20 +902,19 @@ class Server extends EventEmitter implements LoggerAwareInterface {
yield [
$subPropFind,
- $childNode
+ $childNode,
];
- if (($newDepth === self::DEPTH_INFINITY || $newDepth >= 1) && $childNode instanceof ICollection) {
+ if ((self::DEPTH_INFINITY === $newDepth || $newDepth >= 1) && $childNode instanceof ICollection) {
foreach ($this->generatePathNodes($subPropFind) as $subItem) {
yield $subItem;
}
}
-
}
}
/**
- * Returns a list of properties for a given path
+ * Returns a list of properties for a given path.
*
* The path that should be supplied should have the baseUrl stripped out
* The list of properties should be supplied in Clark notation. If the list is empty
@@ -928,20 +923,21 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* If a depth of 1 is requested child elements will also be returned.
*
* @param string $path
- * @param array $propertyNames
- * @param int $depth
+ * @param array $propertyNames
+ * @param int $depth
+ *
* @return array
*
* @deprecated Use getPropertiesIteratorForPath() instead (as it's more memory efficient)
* @see getPropertiesIteratorForPath()
*/
- function getPropertiesForPath($path, $propertyNames = [], $depth = 0) {
-
+ public function getPropertiesForPath($path, $propertyNames = [], $depth = 0)
+ {
return iterator_to_array($this->getPropertiesIteratorForPath($path, $propertyNames, $depth));
-
}
+
/**
- * Returns a list of properties for a given path
+ * Returns a list of properties for a given path.
*
* The path that should be supplied should have the baseUrl stripped out
* The list of properties should be supplied in Clark notation. If the list is empty
@@ -950,33 +946,35 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* If a depth of 1 is requested child elements will also be returned.
*
* @param string $path
- * @param array $propertyNames
- * @param int $depth
+ * @param array $propertyNames
+ * @param int $depth
+ *
* @return \Iterator
*/
- function getPropertiesIteratorForPath($path, $propertyNames = [], $depth = 0) {
-
+ public function getPropertiesIteratorForPath($path, $propertyNames = [], $depth = 0)
+ {
// The only two options for the depth of a propfind is 0 or 1 - as long as depth infinity is not enabled
- if (!$this->enablePropfindDepthInfinity && $depth != 0) $depth = 1;
+ if (!$this->enablePropfindDepthInfinity && 0 != $depth) {
+ $depth = 1;
+ }
$path = trim($path, '/');
$propFindType = $propertyNames ? PropFind::NORMAL : PropFind::ALLPROPS;
- $propFind = new PropFind($path, (array)$propertyNames, $depth, $propFindType);
+ $propFind = new PropFind($path, (array) $propertyNames, $depth, $propFindType);
$parentNode = $this->tree->getNodeForPath($path);
$propFindRequests = [[
$propFind,
- $parentNode
+ $parentNode,
]];
- if (($depth > 0 || $depth === self::DEPTH_INFINITY) && $parentNode instanceof ICollection) {
+ if (($depth > 0 || self::DEPTH_INFINITY === $depth) && $parentNode instanceof ICollection) {
$propFindRequests = $this->generatePathNodes(clone $propFind, current($propFindRequests));
}
foreach ($propFindRequests as $propFindRequest) {
-
list($propFind, $node) = $propFindRequest;
$r = $this->getPropertiesByNode($propFind, $node);
if ($r) {
@@ -993,9 +991,7 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
yield $result;
}
-
}
-
}
/**
@@ -1010,17 +1006,17 @@ class Server extends EventEmitter implements LoggerAwareInterface {
*
* @param array $paths
* @param array $propertyNames
+ *
* @return array
*/
- function getPropertiesForMultiplePaths(array $paths, array $propertyNames = []) {
-
+ public function getPropertiesForMultiplePaths(array $paths, array $propertyNames = [])
+ {
$result = [
];
$nodes = $this->tree->getMultipleNodes($paths);
foreach ($nodes as $path => $node) {
-
$propFind = new PropFind($path, $propertyNames);
$r = $this->getPropertiesByNode($propFind, $node);
if ($r) {
@@ -1032,14 +1028,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$result[$path]['href'] .= '/';
}
}
-
}
return $result;
-
}
-
/**
* Determines all properties for a node.
*
@@ -1051,13 +1044,13 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* list of properties.
*
* @param PropFind $propFind
- * @param INode $node
+ * @param INode $node
+ *
* @return bool
*/
- function getPropertiesByNode(PropFind $propFind, INode $node) {
-
+ public function getPropertiesByNode(PropFind $propFind, INode $node)
+ {
return $this->emit('propFind', [$propFind, $node]);
-
}
/**
@@ -1072,13 +1065,16 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* @param string $uri
* @param resource $data
* @param string $etag
+ *
* @return bool
*/
- function createFile($uri, $data, &$etag = null) {
+ public function createFile($uri, $data, &$etag = null)
+ {
+ list($dir, $name) = Uri\split($uri);
- list($dir, $name) = URLUtil::splitPath($uri);
-
- if (!$this->emit('beforeBind', [$uri])) return false;
+ if (!$this->emit('beforeBind', [$uri])) {
+ return false;
+ }
$parent = $this->tree->getNodeForPath($dir);
if (!$parent instanceof ICollection) {
@@ -1091,13 +1087,17 @@ class Server extends EventEmitter implements LoggerAwareInterface {
//
// If $modified is true, we must not send back an ETag.
$modified = false;
- if (!$this->emit('beforeCreateFile', [$uri, &$data, $parent, &$modified])) return false;
+ if (!$this->emit('beforeCreateFile', [$uri, &$data, $parent, &$modified])) {
+ return false;
+ }
$etag = $parent->createFile($name, $data);
- if ($modified) $etag = null;
+ if ($modified) {
+ $etag = null;
+ }
- $this->tree->markDirty($dir . '/' . $name);
+ $this->tree->markDirty($dir.'/'.$name);
$this->emit('afterBind', [$uri]);
$this->emit('afterCreateFile', [$uri, $parent]);
@@ -1113,10 +1113,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* @param string $uri
* @param resource $data
* @param string $etag
+ *
* @return bool
*/
- function updateFile($uri, $data, &$etag = null) {
-
+ public function updateFile($uri, $data, &$etag = null)
+ {
$node = $this->tree->getNodeForPath($uri);
// It is possible for an event handler to modify the content of the
@@ -1125,47 +1126,46 @@ class Server extends EventEmitter implements LoggerAwareInterface {
//
// If $modified is true, we must not send back an ETag.
$modified = false;
- if (!$this->emit('beforeWriteContent', [$uri, $node, &$data, &$modified])) return false;
+ if (!$this->emit('beforeWriteContent', [$uri, $node, &$data, &$modified])) {
+ return false;
+ }
$etag = $node->put($data);
- if ($modified) $etag = null;
+ if ($modified) {
+ $etag = null;
+ }
$this->emit('afterWriteContent', [$uri, $node]);
return true;
}
-
-
/**
* This method is invoked by sub-systems creating a new directory.
*
* @param string $uri
- * @return void
*/
- function createDirectory($uri) {
-
+ public function createDirectory($uri)
+ {
$this->createCollection($uri, new MkCol(['{DAV:}collection'], []));
-
}
/**
- * Use this method to create a new collection
+ * Use this method to create a new collection.
+ *
+ * @param string $uri The new uri
+ * @param MkCol $mkCol
*
- * @param string $uri The new uri
- * @param MkCol $mkCol
* @return array|null
*/
- function createCollection($uri, MkCol $mkCol) {
-
- list($parentUri, $newName) = URLUtil::splitPath($uri);
+ public function createCollection($uri, MkCol $mkCol)
+ {
+ list($parentUri, $newName) = Uri\split($uri);
// Making sure the parent exists
try {
$parent = $this->tree->getNodeForPath($parentUri);
-
} catch (Exception\NotFound $e) {
throw new Exception\Conflict('Parent node does not exist');
-
}
// Making sure the parent is a collection
@@ -1179,26 +1179,23 @@ class Server extends EventEmitter implements LoggerAwareInterface {
// If we got here.. it means there's already a node on that url, and we need to throw a 405
throw new Exception\MethodNotAllowed('The resource you tried to create already exists');
-
} catch (Exception\NotFound $e) {
// NotFound is the expected behavior.
}
-
- if (!$this->emit('beforeBind', [$uri])) return;
+ if (!$this->emit('beforeBind', [$uri])) {
+ return;
+ }
if ($parent instanceof IExtendedCollection) {
-
- /**
+ /*
* If the parent is an instance of IExtendedCollection, it means that
* we can pass the MkCol object directly as it may be able to store
* properties immediately.
*/
$parent->createExtendedCollection($newName, $mkCol);
-
} else {
-
- /**
+ /*
* If the parent is a standard ICollection, it means only
* 'standard' collections can be created, so we should fail any
* MKCOL operation that carries extra resourcetypes.
@@ -1208,7 +1205,6 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
$parent->createDirectory($newName);
-
}
// If there are any properties that have not been handled/stored,
@@ -1227,23 +1223,21 @@ class Server extends EventEmitter implements LoggerAwareInterface {
];
foreach ($result as $propertyName => $status) {
-
if (!isset($formattedResult[$status])) {
$formattedResult[$status] = [];
}
$formattedResult[$status][$propertyName] = null;
-
}
+
return $formattedResult;
}
$this->tree->markDirty($parentUri);
$this->emit('afterBind', [$uri]);
-
}
/**
- * This method updates a resource's properties
+ * This method updates a resource's properties.
*
* The properties array must be a list of properties. Array-keys are
* property names in clarknotation, array-values are it's values.
@@ -1256,17 +1250,17 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* as their values.
*
* @param string $path
- * @param array $properties
+ * @param array $properties
+ *
* @return array
*/
- function updateProperties($path, array $properties) {
-
+ public function updateProperties($path, array $properties)
+ {
$propPatch = new PropPatch($properties);
$this->emit('propPatch', [$path, $propPatch]);
$propPatch->commit();
return $propPatch->getResult();
-
}
/**
@@ -1287,19 +1281,19 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* related to If-None-Match, If-Match and If-Unmodified Since. It will
* set the status to 304 Not Modified for If-Modified_since.
*
- * @param RequestInterface $request
+ * @param RequestInterface $request
* @param ResponseInterface $response
+ *
* @return bool
*/
- function checkPreconditions(RequestInterface $request, ResponseInterface $response) {
-
+ public function checkPreconditions(RequestInterface $request, ResponseInterface $response)
+ {
$path = $request->getPath();
$node = null;
$lastMod = null;
$etag = null;
if ($ifMatch = $request->getHeader('If-Match')) {
-
// If-Match contains an entity tag. Only if the entity-tag
// matches we are allowed to make the request succeed.
// If the entity-tag is '*' we are only allowed to make the
@@ -1311,13 +1305,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
// Only need to check entity tags if they are not *
- if ($ifMatch !== '*') {
-
+ if ('*' !== $ifMatch) {
// There can be multiple ETags
$ifMatch = explode(',', $ifMatch);
$haveMatch = false;
foreach ($ifMatch as $ifMatchItem) {
-
// Stripping any extra spaces
$ifMatchItem = trim($ifMatchItem, ' ');
@@ -1331,17 +1323,17 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$haveMatch = true;
}
}
-
}
if (!$haveMatch) {
- if ($etag) $response->setHeader('ETag', $etag);
- throw new Exception\PreconditionFailed('An If-Match header was specified, but none of the specified the ETags matched.', 'If-Match');
+ if ($etag) {
+ $response->setHeader('ETag', $etag);
+ }
+ throw new Exception\PreconditionFailed('An If-Match header was specified, but none of the specified ETags matched.', 'If-Match');
}
}
}
if ($ifNoneMatch = $request->getHeader('If-None-Match')) {
-
// The If-None-Match header contains an ETag.
// Only if the ETag does not match the current ETag, the request will succeed
// The header can also contain *, in which case the request
@@ -1356,46 +1348,46 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
if ($nodeExists) {
$haveMatch = false;
- if ($ifNoneMatch === '*') $haveMatch = true;
- else {
-
+ if ('*' === $ifNoneMatch) {
+ $haveMatch = true;
+ } else {
// There might be multiple ETags
$ifNoneMatch = explode(',', $ifNoneMatch);
$etag = $node instanceof IFile ? $node->getETag() : null;
foreach ($ifNoneMatch as $ifNoneMatchItem) {
-
// Stripping any extra spaces
$ifNoneMatchItem = trim($ifNoneMatchItem, ' ');
- if ($etag === $ifNoneMatchItem) $haveMatch = true;
-
+ if ($etag === $ifNoneMatchItem) {
+ $haveMatch = true;
+ }
}
-
}
if ($haveMatch) {
- if ($etag) $response->setHeader('ETag', $etag);
- if ($request->getMethod() === 'GET') {
+ if ($etag) {
+ $response->setHeader('ETag', $etag);
+ }
+ if ('GET' === $request->getMethod()) {
$response->setStatus(304);
+
return false;
} else {
throw new Exception\PreconditionFailed('An If-None-Match header was specified, but the ETag matched (or * was specified).', 'If-None-Match');
}
}
}
-
}
if (!$ifNoneMatch && ($ifModifiedSince = $request->getHeader('If-Modified-Since'))) {
-
// The If-Modified-Since header contains a date. We
// will only return the entity if it has been changed since
// that date. If it hasn't been changed, we return a 304
// header
// Note that this header only has to be checked if there was no If-None-Match header
// as per the HTTP spec.
- $date = HTTP\Util::parseHTTPDate($ifModifiedSince);
+ $date = HTTP\parseDate($ifModifiedSince);
if ($date) {
if (is_null($node)) {
@@ -1403,10 +1395,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
$lastMod = $node->getLastModified();
if ($lastMod) {
- $lastMod = new \DateTime('@' . $lastMod);
+ $lastMod = new \DateTime('@'.$lastMod);
if ($lastMod <= $date) {
$response->setStatus(304);
- $response->setHeader('Last-Modified', HTTP\Util::toHTTPDate($lastMod));
+ $response->setHeader('Last-Modified', HTTP\toDate($lastMod));
+
return false;
}
}
@@ -1414,10 +1407,9 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
if ($ifUnmodifiedSince = $request->getHeader('If-Unmodified-Since')) {
-
// The If-Unmodified-Since will allow allow the request if the
// entity has not changed since the specified date.
- $date = HTTP\Util::parseHTTPDate($ifUnmodifiedSince);
+ $date = HTTP\parseDate($ifUnmodifiedSince);
// We must only check the date if it's valid
if ($date) {
@@ -1426,13 +1418,12 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
$lastMod = $node->getLastModified();
if ($lastMod) {
- $lastMod = new \DateTime('@' . $lastMod);
+ $lastMod = new \DateTime('@'.$lastMod);
if ($lastMod > $date) {
throw new Exception\PreconditionFailed('An If-Unmodified-Since header was specified, but the entity has been changed since the specified date.', 'If-Unmodified-Since');
}
}
}
-
}
// Now the hardest, the If: header. The If: header can contain multiple
@@ -1461,13 +1452,11 @@ class Server extends EventEmitter implements LoggerAwareInterface {
// Every ifCondition needs to validate to true, so we exit as soon as
// we have an invalid condition.
foreach ($ifConditions as $ifCondition) {
-
$uri = $ifCondition['uri'];
$tokens = $ifCondition['tokens'];
// We only need 1 valid token for the condition to succeed.
foreach ($tokens as $token) {
-
$tokenValid = $token['validToken'] || !$token['token'];
$etagValid = false;
@@ -1477,35 +1466,28 @@ class Server extends EventEmitter implements LoggerAwareInterface {
// Checking the ETag, only if the token was already deemed
// valid and there is one.
if ($token['etag'] && $tokenValid) {
-
// The token was valid, and there was an ETag. We must
// grab the current ETag and check it.
$node = $this->tree->getNodeForPath($uri);
$etagValid = $node instanceof IFile && $node->getETag() == $token['etag'];
-
}
-
if (($tokenValid && $etagValid) ^ $token['negate']) {
// Both were valid, so we can go to the next condition.
continue 2;
}
-
-
}
// If we ended here, it means there was no valid ETag + token
// combination found for the current condition. This means we fail!
- throw new Exception\PreconditionFailed('Failed to find a valid token/etag combination for ' . $uri, 'If');
-
+ throw new Exception\PreconditionFailed('Failed to find a valid token/etag combination for '.$uri, 'If');
}
return true;
-
}
/**
- * This method is created to extract information from the WebDAV HTTP 'If:' header
+ * This method is created to extract information from the WebDAV HTTP 'If:' header.
*
* The If header can be quite complex, and has a bunch of features. We're using a regex to extract all relevant information
* The function will return an array, containing structs with the following keys
@@ -1573,12 +1555,15 @@ class Server extends EventEmitter implements LoggerAwareInterface {
* ]
*
* @param RequestInterface $request
+ *
* @return array
*/
- function getIfConditions(RequestInterface $request) {
-
+ public function getIfConditions(RequestInterface $request)
+ {
$header = $request->getHeader('If');
- if (!$header) return [];
+ if (!$header) {
+ return [];
+ }
$matches = [];
@@ -1588,18 +1573,16 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$conditions = [];
foreach ($matches as $match) {
-
// If there was no uri specified in this match, and there were
// already conditions parsed, we add the condition to the list of
// conditions for the previous uri.
if (!$match['uri'] && count($conditions)) {
$conditions[count($conditions) - 1]['tokens'][] = [
'negate' => $match['not'] ? true : false,
- 'token' => $match['token'],
- 'etag' => isset($match['etag']) ? $match['etag'] : ''
+ 'token' => $match['token'],
+ 'etag' => isset($match['etag']) ? $match['etag'] : '',
];
} else {
-
if (!$match['uri']) {
$realUri = $request->getPath();
} else {
@@ -1607,55 +1590,55 @@ class Server extends EventEmitter implements LoggerAwareInterface {
}
$conditions[] = [
- 'uri' => $realUri,
+ 'uri' => $realUri,
'tokens' => [
[
'negate' => $match['not'] ? true : false,
- 'token' => $match['token'],
- 'etag' => isset($match['etag']) ? $match['etag'] : ''
- ]
+ 'token' => $match['token'],
+ 'etag' => isset($match['etag']) ? $match['etag'] : '',
+ ],
],
-
];
}
-
}
return $conditions;
-
}
/**
* Returns an array with resourcetypes for a node.
*
* @param INode $node
+ *
* @return array
*/
- function getResourceTypeForNode(INode $node) {
-
+ public function getResourceTypeForNode(INode $node)
+ {
$result = [];
foreach ($this->resourceTypeMapping as $className => $resourceType) {
- if ($node instanceof $className) $result[] = $resourceType;
+ if ($node instanceof $className) {
+ $result[] = $resourceType;
+ }
}
- return $result;
+ return $result;
}
// }}}
// {{{ XML Readers & Writers
-
/**
* Generates a WebDAV propfind response body based on a list of nodes.
*
* If 'strip404s' is set to true, all 404 responses will be removed.
*
* @param array|\Traversable $fileProperties The list with nodes
- * @param bool $strip404s
+ * @param bool $strip404s
+ *
* @return string
*/
- function generateMultiStatus($fileProperties, $strip404s = false) {
-
+ public function generateMultiStatus($fileProperties, $strip404s = false)
+ {
$w = $this->xml->getWriter();
$w->openMemory();
$w->contextUri = $this->baseUri;
@@ -1664,7 +1647,6 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$w->startElement('{DAV:}multistatus');
foreach ($fileProperties as $entry) {
-
$href = $entry['href'];
unset($entry['href']);
if ($strip404s) {
@@ -1675,14 +1657,12 @@ class Server extends EventEmitter implements LoggerAwareInterface {
$entry
);
$w->write([
- 'name' => '{DAV:}response',
- 'value' => $response
+ 'name' => '{DAV:}response',
+ 'value' => $response,
]);
}
$w->endElement();
return $w->outputMemory();
-
}
-
}