aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/dav/lib/DAV
diff options
context:
space:
mode:
authorMario Vavti <mario@mariovavti.com>2016-05-28 17:46:24 +0200
committerMario Vavti <mario@mariovavti.com>2016-05-28 17:46:24 +0200
commit66effbfe0827fc61fff6d248797a894213ad20d6 (patch)
tree0fbb5ca644e1140e5b3b44b1adc874043790c388 /vendor/sabre/dav/lib/DAV
parentac4688eac087854bf8cb0c893d7a79052ad63a20 (diff)
downloadvolse-hubzilla-66effbfe0827fc61fff6d248797a894213ad20d6.tar.gz
volse-hubzilla-66effbfe0827fc61fff6d248797a894213ad20d6.tar.bz2
volse-hubzilla-66effbfe0827fc61fff6d248797a894213ad20d6.zip
upgrade to sabre32
Diffstat (limited to 'vendor/sabre/dav/lib/DAV')
-rw-r--r--vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php6
-rw-r--r--vendor/sabre/dav/lib/DAV/Auth/Plugin.php126
-rw-r--r--vendor/sabre/dav/lib/DAV/Browser/Plugin.php13
-rw-r--r--vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css6
-rw-r--r--vendor/sabre/dav/lib/DAV/Client.php19
-rw-r--r--vendor/sabre/dav/lib/DAV/CorePlugin.php40
-rw-r--r--vendor/sabre/dav/lib/DAV/FS/Directory.php6
-rw-r--r--vendor/sabre/dav/lib/DAV/File.php20
-rw-r--r--vendor/sabre/dav/lib/DAV/ICollection.php4
-rw-r--r--vendor/sabre/dav/lib/DAV/IFile.php2
-rw-r--r--vendor/sabre/dav/lib/DAV/INode.php5
-rw-r--r--vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php33
-rw-r--r--vendor/sabre/dav/lib/DAV/Server.php39
-rw-r--r--vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php69
-rw-r--r--vendor/sabre/dav/lib/DAV/Sharing/Plugin.php342
-rw-r--r--vendor/sabre/dav/lib/DAV/Tree.php2
-rw-r--r--vendor/sabre/dav/lib/DAV/Version.php2
-rw-r--r--vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php199
-rw-r--r--vendor/sabre/dav/lib/DAV/Xml/Property/Href.php17
-rw-r--r--vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php70
-rw-r--r--vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php48
-rw-r--r--vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php143
-rw-r--r--vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php81
23 files changed, 1204 insertions, 88 deletions
diff --git a/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php b/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php
index 0251decc1..85c5f30d5 100644
--- a/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php
+++ b/vendor/sabre/dav/lib/DAV/Auth/Backend/AbstractDigest.php
@@ -155,8 +155,14 @@ abstract class AbstractDigest implements BackendInterface {
$response
);
$auth->init();
+
+ $oldStatus = $response->getStatus() ?: 200;
$auth->requireLogin();
+ // Preventing the digest utility from modifying the http status code,
+ // this should be handled by the main plugin.
+ $response->setStatus($oldStatus);
+
}
}
diff --git a/vendor/sabre/dav/lib/DAV/Auth/Plugin.php b/vendor/sabre/dav/lib/DAV/Auth/Plugin.php
index 818d8a4ad..4b5f35ac3 100644
--- a/vendor/sabre/dav/lib/DAV/Auth/Plugin.php
+++ b/vendor/sabre/dav/lib/DAV/Auth/Plugin.php
@@ -4,7 +4,6 @@ namespace Sabre\DAV\Auth;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
-use Sabre\HTTP\URLUtil;
use Sabre\DAV\Exception\NotAuthenticated;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
@@ -26,6 +25,20 @@ use Sabre\DAV\ServerPlugin;
class Plugin extends ServerPlugin {
/**
+ * By default this plugin will require that the user is authenticated,
+ * and refuse any access if the user is not authenticated.
+ *
+ * If this setting is set to false, we let the user through, whether they
+ * are authenticated or not.
+ *
+ * This is useful if you want to allow both authenticated and
+ * unauthenticated access to your server.
+ *
+ * @param bool
+ */
+ public $autoRequireLogin = true;
+
+ /**
* authentication backends
*/
protected $backends;
@@ -108,27 +121,6 @@ class Plugin extends ServerPlugin {
}
/**
- * Returns the current username.
- *
- * This method is deprecated and is only kept for backwards compatibility
- * purposes. Please switch to getCurrentPrincipal().
- *
- * @deprecated Will be removed in a future version!
- * @return string|null
- */
- function getCurrentUser() {
-
- // We just do a 'basename' on the principal to give back a sane value
- // here.
- list(, $userName) = URLUtil::splitPath(
- $this->getCurrentPrincipal()
- );
-
- return $userName;
-
- }
-
- /**
* This method is called before any HTTP method and forces users to be authenticated
*
* @param RequestInterface $request
@@ -154,6 +146,50 @@ class Plugin extends ServerPlugin {
return;
}
+
+ $authResult = $this->check($request, $response);
+
+ if ($authResult[0]) {
+ // Auth was successful
+ $this->currentPrincipal = $authResult[1];
+ $this->loginFailedReasons = null;
+ return;
+ }
+
+
+
+ // If we got here, it means that no authentication backend was
+ // successful in authenticating the user.
+ $this->currentPrincipal = null;
+ $this->loginFailedReasons = $authResult[1];
+
+ if ($this->autoRequireLogin) {
+ $this->challenge($request, $response);
+ throw new NotAuthenticated(implode(', ', $authResult[1]));
+ }
+
+ }
+
+ /**
+ * Checks authentication credentials, and logs the user in if possible.
+ *
+ * This method returns an array. The first item in the array is a boolean
+ * indicating if login was successful.
+ *
+ * If login was successful, the second item in the array will contain the
+ * current principal url/path of the logged in user.
+ *
+ * If login was not successful, the second item in the array will contain a
+ * an array with strings. The strings are a list of reasons why login was
+ * unsuccesful. For every auth backend there will be one reason, so usually
+ * there's just one.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return array
+ */
+ function check(RequestInterface $request, ResponseInterface $response) {
+
if (!$this->backends) {
throw new \Sabre\DAV\Exception('No authentication backends were configured on this server.');
}
@@ -172,20 +208,56 @@ class Plugin extends ServerPlugin {
if ($result[0]) {
$this->currentPrincipal = $result[1];
// Exit early
- return;
+ return [true, $result[1]];
}
$reasons[] = $result[1];
}
- // If we got here, it means that no authentication backend was
- // successful in authenticating the user.
- $this->currentPrincipal = null;
+ return [false, $reasons];
+
+ }
+
+ /**
+ * This method sends authentication challenges to the user.
+ *
+ * This method will for example cause a HTTP Basic backend to set a
+ * WWW-Authorization header, indicating to the client that it should
+ * authenticate.
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return array
+ */
+ function challenge(RequestInterface $request, ResponseInterface $response) {
foreach ($this->backends as $backend) {
$backend->challenge($request, $response);
}
- throw new NotAuthenticated(implode(', ', $reasons));
+
+ }
+
+ /**
+ * List of reasons why login failed for the last login operation.
+ *
+ * @var string[]|null
+ */
+ protected $loginFailedReasons;
+
+ /**
+ * Returns a list of reasons why login was unsuccessful.
+ *
+ * This method will return the login failed reasons for the last login
+ * operation. One for each auth backend.
+ *
+ * This method returns null if the last authentication attempt was
+ * successful, or if there was no authentication attempt yet.
+ *
+ * @return string[]|null
+ */
+ function getLoginFailedReasons() {
+
+ return $this->loginFailedReasons;
}
diff --git a/vendor/sabre/dav/lib/DAV/Browser/Plugin.php b/vendor/sabre/dav/lib/DAV/Browser/Plugin.php
index 07ca6c3e5..49359a045 100644
--- a/vendor/sabre/dav/lib/DAV/Browser/Plugin.php
+++ b/vendor/sabre/dav/lib/DAV/Browser/Plugin.php
@@ -48,7 +48,7 @@ class Plugin extends DAV\ServerPlugin {
public $uninterestingProperties = [
'{DAV:}supportedlock',
'{DAV:}acl-restrictions',
- '{DAV:}supported-privilege-set',
+// '{DAV:}supported-privilege-set',
'{DAV:}supported-method-set',
];
@@ -112,7 +112,7 @@ class Plugin extends DAV\ServerPlugin {
$getVars = $request->getQueryParameters();
// CSP headers
- $this->server->httpResponse->setHeader('Content-Security-Policy', "img-src 'self'; style-src 'self';");
+ $this->server->httpResponse->setHeader('Content-Security-Policy', "default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';");
$sabreAction = isset($getVars['sabreAction']) ? $getVars['sabreAction'] : null;
@@ -354,7 +354,7 @@ class Plugin extends DAV\ServerPlugin {
$output = '';
if ($this->enablePost) {
- $this->server->emit('onHTMLActionsPanel', [$node, &$output]);
+ $this->server->emit('onHTMLActionsPanel', [$node, &$output, $path]);
}
if ($output) {
@@ -368,7 +368,7 @@ class Plugin extends DAV\ServerPlugin {
$html .= $this->generateFooter();
- $this->server->httpResponse->setHeader('Content-Security-Policy', "img-src 'self'; style-src 'self';");
+ $this->server->httpResponse->setHeader('Content-Security-Policy', "default-src 'none'; img-src 'self'; style-src 'self'; font-src 'self';");
return $html;
@@ -477,7 +477,7 @@ HTML;
$version = DAV\Version::VERSION;
return <<<HTML
-<footer>Generated by SabreDAV $version (c)2007-2015 <a href="http://sabre.io/">http://sabre.io/</a></footer>
+<footer>Generated by SabreDAV $version (c)2007-2016 <a href="http://sabre.io/">http://sabre.io/</a></footer>
</body>
</html>
HTML;
@@ -493,9 +493,10 @@ HTML;
*
* @param DAV\INode $node
* @param mixed $output
+ * @param string $path
* @return void
*/
- function htmlActionsPanel(DAV\INode $node, &$output) {
+ function htmlActionsPanel(DAV\INode $node, &$output, $path) {
if (!$node instanceof DAV\ICollection)
return;
diff --git a/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css b/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css
index c9ab2c74f..8869597f0 100644
--- a/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css
+++ b/vendor/sabre/dav/lib/DAV/Browser/assets/sabredav.css
@@ -96,12 +96,12 @@ header a {
vertical-align: middle;
border: 0;
}
-input, button {
+input, button, select {
font: inherit;
color: inherit;
}
-input[type=text] {
+input[type=text], select {
border: 1px solid #bbbbbb;
line-height: 22px;
padding: 5px 10px;
@@ -200,7 +200,7 @@ section table {
line-height: 40px;
}
-.actions input[type=text] {
+.actions input[type=text], select {
width: 450px;
}
diff --git a/vendor/sabre/dav/lib/DAV/Client.php b/vendor/sabre/dav/lib/DAV/Client.php
index d46b397b6..08d5d4702 100644
--- a/vendor/sabre/dav/lib/DAV/Client.php
+++ b/vendor/sabre/dav/lib/DAV/Client.php
@@ -3,6 +3,7 @@
namespace Sabre\DAV;
use Sabre\HTTP;
+use Sabre\Uri;
/**
* SabreDAV DAV client
@@ -387,20 +388,10 @@ class Client extends HTTP\Client {
*/
function getAbsoluteUrl($url) {
- // If the url starts with http:// or https://, the url is already absolute.
- if (preg_match('/^http(s?):\/\//', $url)) {
- return $url;
- }
-
- // If the url starts with a slash, we must calculate the url based off
- // the root of the base url.
- if (strpos($url, '/') === 0) {
- $parts = parse_url($this->baseUri);
- return $parts['scheme'] . '://' . $parts['host'] . (isset($parts['port']) ? ':' . $parts['port'] : '') . $url;
- }
-
- // Otherwise...
- return $this->baseUri . $url;
+ return Uri\resolve(
+ $this->baseUri,
+ $url
+ );
}
diff --git a/vendor/sabre/dav/lib/DAV/CorePlugin.php b/vendor/sabre/dav/lib/DAV/CorePlugin.php
index 3a70b2a7e..a1b052915 100644
--- a/vendor/sabre/dav/lib/DAV/CorePlugin.php
+++ b/vendor/sabre/dav/lib/DAV/CorePlugin.php
@@ -50,6 +50,8 @@ class CorePlugin extends ServerPlugin {
$server->on('propFind', [$this, 'propFindNode'], 120);
$server->on('propFind', [$this, 'propFindLate'], 200);
+ $server->on('exception', [$this, 'exception']);
+
}
/**
@@ -844,10 +846,8 @@ class CorePlugin extends ServerPlugin {
if ($node instanceof IProperties && $propertyNames = $propFind->get404Properties()) {
$nodeProperties = $node->getProperties($propertyNames);
- foreach ($propertyNames as $propertyName) {
- if (array_key_exists($propertyName, $nodeProperties)) {
- $propFind->set($propertyName, $nodeProperties[$propertyName], 200);
- }
+ foreach ($nodeProperties as $propertyName => $propertyValue) {
+ $propFind->set($propertyName, $propertyValue, 200);
}
}
@@ -905,6 +905,38 @@ class CorePlugin extends ServerPlugin {
}
/**
+ * Listens for exception events, and automatically logs them.
+ *
+ * @param Exception $e
+ */
+ function exception($e) {
+
+ $logLevel = \Psr\Log\LogLevel::CRITICAL;
+ if ($e instanceof \Sabre\DAV\Exception) {
+ // If it's a standard sabre/dav exception, it means we have a http
+ // status code available.
+ $code = $e->getHTTPCode();
+
+ if ($code >= 400 && $code < 500) {
+ // user error
+ $logLevel = \Psr\Log\LogLevel::INFO;
+ } else {
+ // Server-side error. We mark it's as an error, but it's not
+ // critical.
+ $logLevel = \Psr\Log\LogLevel::ERROR;
+ }
+ }
+
+ $this->server->getLogger()->log(
+ $logLevel,
+ 'Uncaught exception',
+ [
+ 'exception' => $e,
+ ]
+ );
+ }
+
+ /**
* Returns a bunch of meta-data about the plugin.
*
* Providing this information is optional, and is mainly displayed by the
diff --git a/vendor/sabre/dav/lib/DAV/FS/Directory.php b/vendor/sabre/dav/lib/DAV/FS/Directory.php
index 963e5554c..362f7a411 100644
--- a/vendor/sabre/dav/lib/DAV/FS/Directory.php
+++ b/vendor/sabre/dav/lib/DAV/FS/Directory.php
@@ -140,10 +140,10 @@ class Directory extends Node implements DAV\ICollection, DAV\IQuota {
* @return array
*/
function getQuotaInfo() {
-
+ $absolute = realpath($this->path);
return [
- disk_total_space($this->path) - disk_free_space($this->path),
- disk_free_space($this->path)
+ disk_total_space($absolute) - disk_free_space($absolute),
+ disk_free_space($absolute)
];
}
diff --git a/vendor/sabre/dav/lib/DAV/File.php b/vendor/sabre/dav/lib/DAV/File.php
index e0a0391db..675956b22 100644
--- a/vendor/sabre/dav/lib/DAV/File.php
+++ b/vendor/sabre/dav/lib/DAV/File.php
@@ -15,12 +15,24 @@ namespace Sabre\DAV;
abstract class File extends Node implements IFile {
/**
- * Updates the data
+ * Replaces the contents of the file.
*
- * data is a readable stream resource.
+ * The data argument is a readable stream resource.
*
- * @param resource $data
- * @return void
+ * After a succesful put operation, you may choose to return an ETag. The
+ * etag must always be surrounded by double-quotes. These quotes must
+ * appear in the actual string you're returning.
+ *
+ * Clients may use the ETag from a PUT request to later on make sure that
+ * when they update the file, the contents haven't changed in the mean
+ * time.
+ *
+ * If you don't plan to store the file byte-by-byte, and you return a
+ * different object on a subsequent GET you are strongly recommended to not
+ * return an ETag, and just return null.
+ *
+ * @param string|resource $data
+ * @return string|null
*/
function put($data) {
diff --git a/vendor/sabre/dav/lib/DAV/ICollection.php b/vendor/sabre/dav/lib/DAV/ICollection.php
index 390d9b741..7793070d3 100644
--- a/vendor/sabre/dav/lib/DAV/ICollection.php
+++ b/vendor/sabre/dav/lib/DAV/ICollection.php
@@ -54,14 +54,14 @@ interface ICollection extends INode {
* exist.
*
* @param string $name
- * @return DAV\INode
+ * @return INode
*/
function getChild($name);
/**
* Returns an array with all the child nodes
*
- * @return DAV\INode[]
+ * @return INode[]
*/
function getChildren();
diff --git a/vendor/sabre/dav/lib/DAV/IFile.php b/vendor/sabre/dav/lib/DAV/IFile.php
index e16a3a58a..37e7cd33c 100644
--- a/vendor/sabre/dav/lib/DAV/IFile.php
+++ b/vendor/sabre/dav/lib/DAV/IFile.php
@@ -32,7 +32,7 @@ interface IFile extends INode {
* different object on a subsequent GET you are strongly recommended to not
* return an ETag, and just return null.
*
- * @param resource $data
+ * @param resource|data $data
* @return string|null
*/
function put($data);
diff --git a/vendor/sabre/dav/lib/DAV/INode.php b/vendor/sabre/dav/lib/DAV/INode.php
index b5e6cb9ef..bb884934d 100644
--- a/vendor/sabre/dav/lib/DAV/INode.php
+++ b/vendor/sabre/dav/lib/DAV/INode.php
@@ -36,9 +36,10 @@ interface INode {
function setName($name);
/**
- * Returns the last modification time, as a unix timestamp
+ * Returns the last modification time, as a unix timestamp. Return null
+ * if the information is not available.
*
- * @return int
+ * @return int|null
*/
function getLastModified();
diff --git a/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php b/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php
index 910e4979d..2fe843884 100644
--- a/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php
+++ b/vendor/sabre/dav/lib/DAV/PropertyStorage/Backend/PDO.php
@@ -88,6 +88,9 @@ class PDO implements BackendInterface {
$stmt->execute([$path]);
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
+ if (gettype($row['value']) === 'resource') {
+ $row['value'] = stream_get_contents($row['value']);
+ }
switch ($row['valuetype']) {
case null :
case self::VT_STRING :
@@ -121,7 +124,26 @@ class PDO implements BackendInterface {
$propPatch->handleRemaining(function($properties) use ($path) {
- $updateStmt = $this->pdo->prepare("REPLACE INTO " . $this->tableName . " (path, name, valuetype, value) VALUES (?, ?, ?, ?)");
+
+ if ($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'pgsql') {
+
+ $updateSql = <<<SQL
+INSERT INTO {$this->tableName} (path, name, valuetype, value)
+VALUES (:path, :name, :valuetype, :value)
+ON CONFLICT (path, name)
+DO UPDATE SET valuetype = :valuetype, value = :value
+SQL;
+
+
+ } else {
+ $updateSql = <<<SQL
+REPLACE INTO {$this->tableName} (path, name, valuetype, value)
+VALUES (:path, :name, :valuetype, :value)
+SQL;
+
+ }
+
+ $updateStmt = $this->pdo->prepare($updateSql);
$deleteStmt = $this->pdo->prepare("DELETE FROM " . $this->tableName . " WHERE path = ? AND name = ?");
foreach ($properties as $name => $value) {
@@ -136,7 +158,14 @@ class PDO implements BackendInterface {
$valueType = self::VT_OBJECT;
$value = serialize($value);
}
- $updateStmt->execute([$path, $name, $valueType, $value]);
+
+ $updateStmt->bindParam('path', $path, \PDO::PARAM_STR);
+ $updateStmt->bindParam('name', $name, \PDO::PARAM_STR);
+ $updateStmt->bindParam('valuetype', $valueType, \PDO::PARAM_INT);
+ $updateStmt->bindParam('value', $value, \PDO::PARAM_LOB);
+
+ $updateStmt->execute();
+
} else {
$deleteStmt->execute([$path, $name]);
}
diff --git a/vendor/sabre/dav/lib/DAV/Server.php b/vendor/sabre/dav/lib/DAV/Server.php
index b37652812..024b7a557 100644
--- a/vendor/sabre/dav/lib/DAV/Server.php
+++ b/vendor/sabre/dav/lib/DAV/Server.php
@@ -8,6 +8,10 @@ use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
use Sabre\HTTP\URLUtil;
use Sabre\Uri;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
/**
* Main DAV server class
@@ -16,7 +20,9 @@ use Sabre\Uri;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
-class Server extends EventEmitter {
+class Server extends EventEmitter implements LoggerAwareInterface {
+
+ use LoggerAwareTrait;
/**
* Infinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree
@@ -431,6 +437,20 @@ class Server extends EventEmitter {
}
/**
+ * Returns the PSR-3 logger objcet.
+ *
+ * @return LoggerInterface
+ */
+ function getLogger() {
+
+ if (!$this->logger) {
+ $this->logger = new NullLogger();
+ }
+ return $this->logger;
+
+ }
+
+ /**
* Handles a http request, and execute a method based on its name
*
* @param RequestInterface $request
@@ -1177,9 +1197,20 @@ class Server extends EventEmitter {
if (!$success) {
$result = $mkCol->getResult();
- // generateMkCol needs the href key to exist.
- $result['href'] = $uri;
- return $result;
+
+ $formattedResult = [
+ 'href' => $uri,
+ ];
+
+ foreach ($result as $propertyName => $status) {
+
+ if (!isset($formattedResult[$status])) {
+ $formattedResult[$status] = [];
+ }
+ $formattedResult[$status][$propertyName] = null;
+
+ }
+ return $formattedResult;
}
$this->tree->markDirty($parentUri);
diff --git a/vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php b/vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php
new file mode 100644
index 000000000..034aefbdc
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Sabre\DAV\Sharing;
+
+use Sabre\DAV\INode;
+
+/**
+ * This interface represents a resource that has sharing capabilities, either
+ * because it's possible for an owner to share the resource, or because this is
+ * an instance of a shared resource.
+ *
+ * @copyright Copyright (C) fruux GmbH. (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+interface ISharedNode extends INode {
+
+ /**
+ * Returns the 'access level' for the instance of this shared resource.
+ *
+ * The value should be one of the Sabre\DAV\Sharing\Plugin::ACCESS_
+ * constants.
+ *
+ * @return int
+ */
+ function getShareAccess();
+
+ /**
+ * This function must return a URI that uniquely identifies the shared
+ * resource. This URI should be identical across instances, and is
+ * also used in several other XML bodies to connect invites to
+ * resources.
+ *
+ * This may simply be a relative reference to the original shared instance,
+ * but it could also be a urn. As long as it's a valid URI and unique.
+ *
+ * @return string
+ */
+ function getShareResourceUri();
+
+ /**
+ * Updates the list of sharees.
+ *
+ * Every item must be a Sharee object.
+ *
+ * @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
+ * @return void
+ */
+ function updateInvites(array $sharees);
+
+ /**
+ * Returns the list of people whom this resource is shared with.
+ *
+ * Every item in the returned array must be a Sharee object with
+ * at least the following properties set:
+ *
+ * * $href
+ * * $shareAccess
+ * * $inviteStatus
+ *
+ * and optionally:
+ *
+ * * $properties
+ *
+ * @return \Sabre\DAV\Xml\Element\Sharee[]
+ */
+ function getInvites();
+
+}
diff --git a/vendor/sabre/dav/lib/DAV/Sharing/Plugin.php b/vendor/sabre/dav/lib/DAV/Sharing/Plugin.php
new file mode 100644
index 000000000..354d06a56
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Sharing/Plugin.php
@@ -0,0 +1,342 @@
+<?php
+
+namespace Sabre\DAV\Sharing;
+
+use Sabre\DAV\Exception\BadRequest;
+use Sabre\DAV\Exception\Forbidden;
+use Sabre\DAV\INode;
+use Sabre\DAV\PropFind;
+use Sabre\DAV\Server;
+use Sabre\DAV\ServerPlugin;
+use Sabre\DAV\Xml\Property;
+use Sabre\DAV\Xml\Element\Sharee;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
+
+/**
+ * This plugin implements HTTP requests and properties related to:
+ *
+ * draft-pot-webdav-resource-sharing
+ *
+ * This specification allows people to share webdav resources with others.
+ *
+ * @copyright Copyright (C) 2007-2015 fruux GmbH. (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class Plugin extends ServerPlugin {
+
+ const ACCESS_NOTSHARED = 0;
+ const ACCESS_SHAREDOWNER = 1;
+ const ACCESS_READ = 2;
+ const ACCESS_READWRITE = 3;
+ const ACCESS_NOACCESS = 4;
+
+ const INVITE_NORESPONSE = 1;
+ const INVITE_ACCEPTED = 2;
+ const INVITE_DECLINED = 3;
+ const INVITE_INVALID = 4;
+
+ /**
+ * Reference to SabreDAV server object.
+ *
+ * @var Sabre\DAV\Server
+ */
+ protected $server;
+
+ /**
+ * This method should return a list of server-features.
+ *
+ * This is for example 'versioning' and is added to the DAV: header
+ * in an OPTIONS response.
+ *
+ * @return array
+ */
+ function getFeatures() {
+
+ return ['resource-sharing'];
+
+ }
+
+ /**
+ * Returns a plugin name.
+ *
+ * Using this name other plugins will be able to access other plugins
+ * using \Sabre\DAV\Server::getPlugin
+ *
+ * @return string
+ */
+ function getPluginName() {
+
+ return 'sharing';
+
+ }
+
+ /**
+ * This initializes the plugin.
+ *
+ * This function is called by Sabre\DAV\Server, after
+ * addPlugin is called.
+ *
+ * This method should set up the required event subscriptions.
+ *
+ * @param Server $server
+ * @return void
+ */
+ function initialize(Server $server) {
+
+ $this->server = $server;
+
+ $server->xml->elementMap['{DAV:}share-resource'] = 'Sabre\\DAV\\Xml\\Request\\ShareResource';
+
+ array_push(
+ $server->protectedProperties,
+ '{DAV:}share-mode'
+ );
+
+ $server->on('method:POST', [$this, 'httpPost']);
+ $server->on('propFind', [$this, 'propFind']);
+ $server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']);
+ $server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']);
+ $server->on('onBrowserPostAction', [$this, 'browserPostAction']);
+
+ }
+
+ /**
+ * Updates the list of sharees on a shared resource.
+ *
+ * The sharees array is a list of people that are to be added modified
+ * or removed in the list of shares.
+ *
+ * @param string $path
+ * @param Sharee[] $sharees
+ * @return void
+ */
+ function shareResource($path, array $sharees) {
+
+ $node = $this->server->tree->getNodeForPath($path);
+
+ if (!$node instanceof ISharedNode) {
+
+ throw new Forbidden('Sharing is not allowed on this node');
+
+ }
+
+ // Getting ACL info
+ $acl = $this->server->getPlugin('acl');
+
+ // If there's no ACL support, we allow everything
+ if ($acl) {
+ $acl->checkPrivileges($path, '{DAV:}share');
+ }
+
+ foreach ($sharees as $sharee) {
+ // We're going to attempt to get a local principal uri for a share
+ // href by emitting the getPrincipalByUri event.
+ $principal = null;
+ $this->server->emit('getPrincipalByUri', [$sharee->href, &$principal]);
+ $sharee->principal = $principal;
+ }
+ $node->updateInvites($sharees);
+
+ }
+
+ /**
+ * This event is triggered when properties are requested for nodes.
+ *
+ * This allows us to inject any sharings-specific properties.
+ *
+ * @param PropFind $propFind
+ * @param INode $node
+ * @return void
+ */
+ function propFind(PropFind $propFind, INode $node) {
+
+ if ($node instanceof ISharedNode) {
+
+ $propFind->handle('{DAV:}share-access', function() use ($node) {
+
+ return new Property\ShareAccess($node->getShareAccess());
+
+ });
+ $propFind->handle('{DAV:}invite', function() use ($node) {
+
+ return new Property\Invite($node->getInvites());
+
+ });
+ $propFind->handle('{DAV:}share-resource-uri', function() use ($node) {
+
+ return new Property\Href($node->getShareResourceUri());
+
+ });
+
+ }
+
+ }
+
+ /**
+ * We intercept this to handle POST requests on shared resources
+ *
+ * @param RequestInterface $request
+ * @param ResponseInterface $response
+ * @return null|bool
+ */
+ function httpPost(RequestInterface $request, ResponseInterface $response) {
+
+ $path = $request->getPath();
+ $contentType = $request->getHeader('Content-Type');
+
+ // We're only interested in the davsharing content type.
+ if (strpos($contentType, 'application/davsharing+xml') === false) {
+ return;
+ }
+
+ $message = $this->server->xml->parse(
+ $request->getBody(),
+ $request->getUrl(),
+ $documentType
+ );
+
+ switch ($documentType) {
+
+ case '{DAV:}share-resource':
+
+ $this->shareResource($path, $message->sharees);
+ $response->setStatus(200);
+ // Adding this because sending a response body may cause issues,
+ // and I wanted some type of indicator the response was handled.
+ $response->setHeader('X-Sabre-Status', 'everything-went-well');
+
+ // Breaking the event chain
+ return false;
+
+ default :
+ throw new BadRequest('Unexpected document type: ' . $documentType . ' for this Content-Type');
+
+ }
+
+ }
+
+ /**
+ * This method is triggered whenever a subsystem reqeuests the privileges
+ * hat are supported on a particular node.
+ *
+ * We need to add a number of privileges for scheduling purposes.
+ *
+ * @param INode $node
+ * @param array $supportedPrivilegeSet
+ */
+ function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) {
+
+ if ($node instanceof ISharedNode) {
+ $supportedPrivilegeSet['{DAV:}share'] = [
+ 'abstract' => false,
+ 'aggregates' => [],
+ ];
+ }
+ }
+
+ /**
+ * Returns a bunch of meta-data about the plugin.
+ *
+ * Providing this information is optional, and is mainly displayed by the
+ * Browser plugin.
+ *
+ * The description key in the returned array may contain html and will not
+ * be sanitized.
+ *
+ * @return array
+ */
+ function getPluginInfo() {
+
+ return [
+ 'name' => $this->getPluginName(),
+ 'description' => 'This plugin implements WebDAV resource sharing',
+ 'link' => 'https://github.com/evert/webdav-sharing'
+ ];
+
+ }
+
+ /**
+ * This method is used to generate HTML output for the
+ * DAV\Browser\Plugin.
+ *
+ * @param INode $node
+ * @param string $output
+ * @param string $path
+ * @return bool|null
+ */
+ function htmlActionsPanel(INode $node, &$output, $path) {
+
+ if (!$node instanceof ISharedNode) {
+ return;
+ }
+
+ $aclPlugin = $this->server->getPlugin('acl');
+ if ($aclPlugin) {
+ if (!$aclPlugin->checkPrivileges($path, '{DAV:}share', \Sabre\DAVACL\Plugin::R_PARENT, false)) {
+ // Sharing is not permitted, we will not draw this interface.
+ return;
+ }
+ }
+
+ $output .= '<tr><td colspan="2"><form method="post" action="">
+ <h3>Share this resource</h3>
+ <input type="hidden" name="sabreAction" value="share" />
+ <label>Share with (uri):</label> <input type="text" name="href" placeholder="mailto:user@example.org"/><br />
+ <label>Access</label>
+ <select name="access">
+ <option value="readwrite">Read-write</option>
+ <option value="read">Read-only</option>
+ <option value="no-access">Revoke access</option>
+ </select><br />
+ <input type="submit" value="share" />
+ </form>
+ </td></tr>';
+
+ }
+
+ /**
+ * This method is triggered for POST actions generated by the browser
+ * plugin.
+ *
+ * @param string $path
+ * @param string $action
+ * @param array $postVars
+ */
+ function browserPostAction($path, $action, $postVars) {
+
+ if ($action !== 'share') {
+ return;
+ }
+
+ if (empty($postVars['href'])) {
+ throw new BadRequest('The "href" POST parameter is required');
+ }
+ if (empty($postVars['access'])) {
+ throw new BadRequest('The "access" POST parameter is required');
+ }
+
+ $accessMap = [
+ 'readwrite' => self::ACCESS_READWRITE,
+ 'read' => self::ACCESS_READ,
+ 'no-access' => self::ACCESS_NOACCESS,
+ ];
+
+ if (!isset($accessMap[$postVars['access']])) {
+ throw new BadRequest('The "access" POST must be readwrite, read or no-access');
+ }
+ $sharee = new Sharee([
+ 'href' => $postVars['href'],
+ 'access' => $accessMap[$postVars['access']],
+ ]);
+
+ $this->shareResource(
+ $path,
+ [$sharee]
+ );
+ return false;
+
+ }
+
+}
diff --git a/vendor/sabre/dav/lib/DAV/Tree.php b/vendor/sabre/dav/lib/DAV/Tree.php
index 4563f7c72..5d2792503 100644
--- a/vendor/sabre/dav/lib/DAV/Tree.php
+++ b/vendor/sabre/dav/lib/DAV/Tree.php
@@ -229,7 +229,7 @@ class Tree {
// flushing the entire cache
$path = trim($path, '/');
foreach ($this->cache as $nodePath => $node) {
- if ($nodePath == $path || strpos($nodePath, $path . '/') === 0)
+ if ($path === '' || $nodePath == $path || strpos($nodePath, $path . '/') === 0)
unset($this->cache[$nodePath]);
}
diff --git a/vendor/sabre/dav/lib/DAV/Version.php b/vendor/sabre/dav/lib/DAV/Version.php
index f9331943a..5430b967c 100644
--- a/vendor/sabre/dav/lib/DAV/Version.php
+++ b/vendor/sabre/dav/lib/DAV/Version.php
@@ -14,6 +14,6 @@ class Version {
/**
* Full version number
*/
- const VERSION = '3.1.3';
+ const VERSION = '3.2.0-beta1';
}
diff --git a/vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php b/vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php
new file mode 100644
index 000000000..dcfd7bd2e
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php
@@ -0,0 +1,199 @@
+<?php
+
+namespace Sabre\DAV\Xml\Element;
+
+use Sabre\DAV\Exception\BadRequest;
+use Sabre\DAV\Sharing\Plugin;
+use Sabre\DAV\Xml\Property\Href;
+use Sabre\DAV\Xml\Property\ShareAccess;
+use Sabre\Xml\Deserializer;
+use Sabre\Xml\Element;
+use Sabre\Xml\Reader;
+use Sabre\Xml\Writer;
+
+/**
+ * This class represents the {DAV:}sharee element.
+ *
+ * @copyright Copyright (C) fruux GmbH. (https://fruux.com/)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class Sharee implements Element {
+
+ /**
+ * A URL. Usually a mailto: address, could also be a principal url.
+ * This uniquely identifies the sharee.
+ *
+ * @var string
+ */
+ public $href;
+
+ /**
+ * A local principal path. The server will do its best to locate the
+ * principal uri based on the given uri. If we could find a local matching
+ * principal uri, this property will contain the value.
+ *
+ * @var string|null
+ */
+ public $principal;
+
+ /**
+ * A list of WebDAV properties that describe the sharee. This might for
+ * example contain a {DAV:}displayname with the real name of the user.
+ *
+ * @var array
+ */
+ public $properties = [];
+
+ /**
+ * Share access level. One of the Sabre\DAV\Sharing\Plugin::ACCESS
+ * constants.
+ *
+ * Can be one of:
+ *
+ * ACCESS_READ
+ * ACCESS_READWRITE
+ * ACCESS_SHAREDOWNER
+ * ACCESS_NOACCESS
+ *
+ * depending on context.
+ *
+ * @var int
+ */
+ public $access;
+
+ /**
+ * When a sharee is originally invited to a share, the sharer may add
+ * a comment. This will be placed in this property.
+ *
+ * @var string
+ */
+ public $comment;
+
+ /**
+ * The status of the invite, should be one of the
+ * Sabre\DAV\Sharing\Plugin::INVITE constants.
+ *
+ * @var int
+ */
+ public $inviteStatus;
+
+ /**
+ * Creates the object
+ *
+ * $properties will be used to populate all internal properties.
+ *
+ * @param array $properties
+ */
+ function __construct(array $properties = []) {
+
+ foreach ($properties as $k => $v) {
+
+ if (property_exists($this, $k)) {
+ $this->$k = $v;
+ } else {
+ throw new \InvalidArgumentException('Unknown property: ' . $k);
+ }
+
+ }
+
+ }
+
+ /**
+ * The xmlSerialize method is called during xml writing.
+ *
+ * Use the $writer argument to write its own xml serialization.
+ *
+ * An important note: do _not_ create a parent element. Any element
+ * implementing XmlSerializble should only ever write what's considered
+ * its 'inner xml'.
+ *
+ * The parent of the current element is responsible for writing a
+ * containing element.
+ *
+ * This allows serializers to be re-used for different element names.
+ *
+ * If you are opening new elements, you must also close them again.
+ *
+ * @param Writer $writer
+ * @return void
+ */
+ function xmlSerialize(Writer $writer) {
+
+
+ $writer->write([
+ new Href($this->href),
+ '{DAV:}prop' => $this->properties,
+ '{DAV:}share-access' => new ShareAccess($this->access),
+ ]);
+ switch ($this->inviteStatus) {
+ case Plugin::INVITE_NORESPONSE :
+ $writer->writeElement('{DAV:}invite-noresponse');
+ break;
+ case Plugin::INVITE_ACCEPTED :
+ $writer->writeElement('{DAV:}invite-accepted');
+ break;
+ case Plugin::INVITE_DECLINED :
+ $writer->writeElement('{DAV:}invite-declined');
+ break;
+ case Plugin::INVITE_INVALID :
+ $writer->writeElement('{DAV:}invite-invalid');
+ break;
+ }
+
+ }
+
+ /**
+ * The deserialize method is called during xml parsing.
+ *
+ * This method is called statictly, this is because in theory this method
+ * may be used as a type of constructor, or factory method.
+ *
+ * Often you want to return an instance of the current class, but you are
+ * free to return other data as well.
+ *
+ * You are responsible for advancing the reader to the next element. Not
+ * doing anything will result in a never-ending loop.
+ *
+ * If you just want to skip parsing for this element altogether, you can
+ * just call $reader->next();
+ *
+ * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+ * the next element.
+ *
+ * @param Reader $reader
+ * @return mixed
+ */
+ static function xmlDeserialize(Reader $reader) {
+
+ // Temporarily override configuration
+ $reader->pushContext();
+ $reader->elementMap['{DAV:}share-access'] = 'Sabre\DAV\Xml\Property\ShareAccess';
+ $reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\keyValue';
+
+ $elems = Deserializer\keyValue($reader, 'DAV:');
+
+ // Restore previous configuration
+ $reader->popContext();
+
+ $sharee = new self();
+ if (!isset($elems['href'])) {
+ throw new BadRequest('Every {DAV:}sharee must have a {DAV:}href child-element');
+ }
+ $sharee->href = $elems['href'];
+
+ if (isset($elems['prop'])) {
+ $sharee->properties = $elems['prop'];
+ }
+ if (isset($elems['comment'])) {
+ $sharee->comment = $elems['comment'];
+ }
+ if (!isset($elems['share-access'])) {
+ throw new BadRequest('Every {DAV:}sharee must have a {DAV:}share-access child element');
+ }
+ $sharee->access = $elems['share-access']->getValue();
+ return $sharee;
+
+ }
+
+}
diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php b/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php
index 538e98d0f..0027f72e1 100644
--- a/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php
+++ b/vendor/sabre/dav/lib/DAV/Xml/Property/Href.php
@@ -7,6 +7,7 @@ use Sabre\DAV\Browser\HtmlOutputHelper;
use Sabre\Xml\Element;
use Sabre\Xml\Reader;
use Sabre\Xml\Writer;
+use Sabre\Uri;
/**
* Href property
@@ -32,13 +33,6 @@ class Href implements Element, HtmlOutput {
protected $hrefs;
/**
- * Automatically prefix the url with the server base directory
- *
- * @var bool
- */
- protected $autoPrefix = true;
-
- /**
* Constructor
*
* You must either pass a string for a single href, or an array of hrefs.
@@ -47,16 +41,13 @@ class Href implements Element, HtmlOutput {
* and not relative to the servers base uri.
*
* @param string|string[] $href
- * @param bool $autoPrefix
*/
- function __construct($hrefs, $autoPrefix = true) {
+ function __construct($hrefs) {
if (is_string($hrefs)) {
$hrefs = [$hrefs];
}
$this->hrefs = $hrefs;
- $this->autoPrefix = $autoPrefix;
-
}
@@ -104,9 +95,7 @@ class Href implements Element, HtmlOutput {
function xmlSerialize(Writer $writer) {
foreach ($this->getHrefs() as $href) {
- if ($this->autoPrefix) {
- $href = $writer->contextUri . \Sabre\HTTP\encodePath($href);
- }
+ $href = Uri\resolve($writer->contextUri, $href);
$writer->writeElement('{DAV:}href', $href);
}
diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php b/vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php
new file mode 100644
index 000000000..0616ff113
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Sabre\DAV\Xml\Property;
+
+use Sabre\DAV\Sharing\Sharee;
+use Sabre\Xml\XmlSerializable;
+use Sabre\Xml\Writer;
+
+/**
+ * This class represents the {DAV:}invite property.
+ *
+ * This property is defined here:
+ * https://tools.ietf.org/html/draft-pot-webdav-resource-sharing-03#section-4.4.2
+ *
+ * This property is used by clients to determine who currently has access to
+ * a shared resource, what their access level is and what their invite status
+ * is.
+ *
+ * @copyright Copyright (C) fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class Invite implements XmlSerializable {
+
+ /**
+ * A list of sharees
+ *
+ * @var Sharee[]
+ */
+ public $sharees = [];
+
+ /**
+ * Creates the property.
+ *
+ * @param Sharee[] $sharees
+ */
+ function __construct(array $sharees) {
+
+ $this->sharees = $sharees;
+
+ }
+
+ /**
+ * The xmlSerialize method is called during xml writing.
+ *
+ * Use the $writer argument to write its own xml serialization.
+ *
+ * An important note: do _not_ create a parent element. Any element
+ * implementing XmlSerializble should only ever write what's considered
+ * its 'inner xml'.
+ *
+ * The parent of the current element is responsible for writing a
+ * containing element.
+ *
+ * This allows serializers to be re-used for different element names.
+ *
+ * If you are opening new elements, you must also close them again.
+ *
+ * @param Writer $writer
+ * @return void
+ */
+ function xmlSerialize(Writer $writer) {
+
+ foreach ($this->sharees as $sharee) {
+ $writer->writeElement('{DAV:}sharee', $sharee);
+ }
+
+ }
+
+}
diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php b/vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php
new file mode 100644
index 000000000..76a27b95d
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php
@@ -0,0 +1,48 @@
+<?php
+
+namespace Sabre\DAV\Xml\Property;
+
+use Sabre\HTTP;
+
+/**
+ * LocalHref property
+ *
+ * Like the Href property, this element represents {DAV:}href. The difference
+ * is that this is used stricly for paths on the server. The LocalHref property
+ * will prepare the path so it's a valid URI.
+ *
+ * These two objects behave identically:
+ * new LocalHref($path)
+ * new Href(\Sabre\HTTP\encodePath($path))
+ *
+ * LocalPath basically ensures that your spaces are %20, and everything that
+ * needs to be is uri encoded.
+ *
+ * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class LocalHref extends Href {
+
+ /**
+ * Constructor
+ *
+ * You must either pass a string for a single href, or an array of hrefs.
+ *
+ * If auto-prefix is set to false, the hrefs will be treated as absolute
+ * and not relative to the servers base uri.
+ *
+ * @param string|string[] $href
+ */
+ function __construct($hrefs) {
+
+ parent::__construct(array_map(
+ function($href) {
+ return \Sabre\HTTP\encodePath($href);
+ },
+ (array)$hrefs
+ ));
+
+ }
+
+}
diff --git a/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php b/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php
new file mode 100644
index 000000000..f27af5415
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Sabre\DAV\Xml\Property;
+
+use Sabre\DAV\Sharing\Plugin as SharingPlugin;
+use Sabre\DAV\Exception\BadRequest;
+use Sabre\Xml\Element;
+use Sabre\Xml\Reader;
+use Sabre\Xml\Writer;
+
+/**
+ * This class represents the {DAV:}share-access property.
+ *
+ * This property is defined here:
+ * https://tools.ietf.org/html/draft-pot-webdav-resource-sharing-03#section-4.4.1
+ *
+ * This property is used to indicate if a resource is a shared resource, and
+ * whether the instance of the shared resource is the original instance, or
+ * an instance belonging to a sharee.
+ *
+ * @copyright Copyright (C) fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class ShareAccess implements Element {
+
+ /**
+ * Either SHARED or SHAREDOWNER
+ *
+ * @var int
+ */
+ protected $value;
+
+ /**
+ * Creates the property.
+ *
+ * The constructor value must be one of the
+ * \Sabre\DAV\Sharing\Plugin::ACCESS_ constants.
+ *
+ * @param int $shareAccess
+ */
+ function __construct($shareAccess) {
+
+ $this->value = $shareAccess;
+
+ }
+
+ /**
+ * Returns the current value.
+ *
+ * @return int
+ */
+ function getValue() {
+
+ return $this->value;
+
+ }
+
+ /**
+ * The xmlSerialize method is called during xml writing.
+ *
+ * Use the $writer argument to write its own xml serialization.
+ *
+ * An important note: do _not_ create a parent element. Any element
+ * implementing XmlSerializble should only ever write what's considered
+ * its 'inner xml'.
+ *
+ * The parent of the current element is responsible for writing a
+ * containing element.
+ *
+ * This allows serializers to be re-used for different element names.
+ *
+ * If you are opening new elements, you must also close them again.
+ *
+ * @param Writer $writer
+ * @return void
+ */
+ function xmlSerialize(Writer $writer) {
+
+ switch ($this->value) {
+
+ case SharingPlugin::ACCESS_NOTSHARED :
+ $writer->writeElement('{DAV:}not-shared');
+ break;
+ case SharingPlugin::ACCESS_SHAREDOWNER :
+ $writer->writeElement('{DAV:}shared-owner');
+ break;
+ case SharingPlugin::ACCESS_READ :
+ $writer->writeElement('{DAV:}read');
+ break;
+ case SharingPlugin::ACCESS_READWRITE :
+ $writer->writeElement('{DAV:}read-write');
+ break;
+ case SharingPlugin::ACCESS_NOACCESS :
+ $writer->writeElement('{DAV:}no-access');
+ break;
+
+ }
+
+ }
+
+ /**
+ * The deserialize method is called during xml parsing.
+ *
+ * This method is called statictly, this is because in theory this method
+ * may be used as a type of constructor, or factory method.
+ *
+ * Often you want to return an instance of the current class, but you are
+ * free to return other data as well.
+ *
+ * You are responsible for advancing the reader to the next element. Not
+ * doing anything will result in a never-ending loop.
+ *
+ * If you just want to skip parsing for this element altogether, you can
+ * just call $reader->next();
+ *
+ * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+ * the next element.
+ *
+ * @param Reader $reader
+ * @return mixed
+ */
+ static function xmlDeserialize(Reader $reader) {
+
+ $elems = $reader->parseInnerTree();
+ foreach ($elems as $elem) {
+ switch ($elem['name']) {
+ case '{DAV:}not-shared' :
+ return new self(SharingPlugin::ACCESS_NOTSHARED);
+ case '{DAV:}sharedowner' :
+ return new self(SharingPlugin::ACCESS_SHAREDOWNER);
+ case '{DAV:}read' :
+ return new self(SharingPlugin::ACCESS_READ);
+ case '{DAV:}read-write' :
+ return new self(SharingPlugin::ACCESS_READWRITE);
+ case '{DAV:}no-access' :
+ return new self(SharingPlugin::ACCESS_NOACCESS);
+ }
+ }
+ throw new BadRequest('Invalid value for {DAV:}share-access element');
+
+ }
+}
diff --git a/vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php b/vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php
new file mode 100644
index 000000000..965e5857c
--- /dev/null
+++ b/vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace Sabre\DAV\Xml\Request;
+
+use Sabre\Xml\Reader;
+use Sabre\Xml\XmlDeserializable;
+use Sabre\DAV\Xml\Element\Sharee;
+
+/**
+ * ShareResource request parser.
+ *
+ * This class parses the {DAV:}share-resource POST request as defined in:
+ *
+ * https://tools.ietf.org/html/draft-pot-webdav-resource-sharing-01#section-5.3.2.1
+ *
+ * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://www.rooftopsolutions.nl/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class ShareResource implements XmlDeserializable {
+
+ /**
+ * The list of new people added or updated or removed from the share.
+ *
+ * @var Sharee[]
+ */
+ public $sharees = [];
+
+ /**
+ * Constructor
+ *
+ * @param Sharee[] $sharees
+ */
+ function __construct(array $sharees) {
+
+ $this->sharees = $sharees;
+
+ }
+
+ /**
+ * The deserialize method is called during xml parsing.
+ *
+ * This method is called statictly, this is because in theory this method
+ * may be used as a type of constructor, or factory method.
+ *
+ * Often you want to return an instance of the current class, but you are
+ * free to return other data as well.
+ *
+ * You are responsible for advancing the reader to the next element. Not
+ * doing anything will result in a never-ending loop.
+ *
+ * If you just want to skip parsing for this element altogether, you can
+ * just call $reader->next();
+ *
+ * $reader->parseInnerTree() will parse the entire sub-tree, and advance to
+ * the next element.
+ *
+ * @param Reader $reader
+ * @return mixed
+ */
+ static function xmlDeserialize(Reader $reader) {
+
+ $elems = $reader->parseInnerTree([
+ '{DAV:}sharee' => 'Sabre\DAV\Xml\Element\Sharee',
+ '{DAV:}share-access' => 'Sabre\DAV\Xml\Property\ShareAccess',
+ '{DAV:}prop' => 'Sabre\Xml\Deserializer\keyValue',
+ ]);
+
+ $sharees = [];
+
+ foreach ($elems as $elem) {
+ if ($elem['name'] !== '{DAV:}sharee') continue;
+ $sharees[] = $elem['value'];
+
+ }
+
+ return new self($sharees);
+
+ }
+
+}