Merge pull request #444 from git-marijus/dev
Merge branch sabre32 into dev
This commit is contained in:
commit
05aba0b4dd
@ -219,7 +219,7 @@ class Browser extends DAV\Browser\Plugin {
|
||||
|
||||
$output = '';
|
||||
if ($this->enablePost) {
|
||||
$this->server->emit('onHTMLActionsPanel', array($parent, &$output));
|
||||
$this->server->emit('onHTMLActionsPanel', array($parent, &$output, $path));
|
||||
}
|
||||
|
||||
$html .= replace_macros(get_markup_template('cloud.tpl'), array(
|
||||
@ -266,7 +266,7 @@ class Browser extends DAV\Browser\Plugin {
|
||||
* @param \Sabre\DAV\INode $node
|
||||
* @param string &$output
|
||||
*/
|
||||
public function htmlActionsPanel(DAV\INode $node, &$output) {
|
||||
public function htmlActionsPanel(DAV\INode $node, &$output, $path) {
|
||||
if (! $node instanceof DAV\ICollection)
|
||||
return;
|
||||
|
||||
|
@ -1909,4 +1909,4 @@ function get_attach_binname($s) {
|
||||
$p = substr($p,strpos($p,'/')+1);
|
||||
}
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
|
2
vendor/autoload.php
vendored
2
vendor/autoload.php
vendored
@ -4,4 +4,4 @@
|
||||
|
||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785::getLoader();
|
||||
return ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c::getLoader();
|
||||
|
4
vendor/composer/autoload_files.php
vendored
4
vendor/composer/autoload_files.php
vendored
@ -7,10 +7,10 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'383eaff206634a77a1be54e64e6459c7' => $vendorDir . '/sabre/uri/lib/functions.php',
|
||||
'3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php',
|
||||
'93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php',
|
||||
'2b9d0f43f9552984cfa82fee95491826' => $vendorDir . '/sabre/event/lib/coroutine.php',
|
||||
'd81bab31d3feb45bfe2f283ea3c8fdf7' => $vendorDir . '/sabre/event/lib/Loop/functions.php',
|
||||
'a1cce3d26cc15c00fcd0b3354bd72c88' => $vendorDir . '/sabre/event/lib/Promise/functions.php',
|
||||
'3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php',
|
||||
'93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php',
|
||||
'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php',
|
||||
);
|
||||
|
1
vendor/composer/autoload_namespaces.php
vendored
1
vendor/composer/autoload_namespaces.php
vendored
@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log'),
|
||||
);
|
||||
|
14
vendor/composer/autoload_real.php
vendored
14
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
class ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@ -19,15 +19,15 @@ class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit02c7a5bb99a87a4c8dbf069d69b1a15c', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
|
||||
if ($useStaticLoader) {
|
||||
require_once __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
@ -48,19 +48,19 @@ class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$files;
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file);
|
||||
composerRequire02c7a5bb99a87a4c8dbf069d69b1a15c($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file)
|
||||
function composerRequire02c7a5bb99a87a4c8dbf069d69b1a15c($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
21
vendor/composer/autoload_static.php
vendored
21
vendor/composer/autoload_static.php
vendored
@ -4,15 +4,15 @@
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
class ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c
|
||||
{
|
||||
public static $files = array (
|
||||
'383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/functions.php',
|
||||
'3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php',
|
||||
'93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php',
|
||||
'2b9d0f43f9552984cfa82fee95491826' => __DIR__ . '/..' . '/sabre/event/lib/coroutine.php',
|
||||
'd81bab31d3feb45bfe2f283ea3c8fdf7' => __DIR__ . '/..' . '/sabre/event/lib/Loop/functions.php',
|
||||
'a1cce3d26cc15c00fcd0b3354bd72c88' => __DIR__ . '/..' . '/sabre/event/lib/Promise/functions.php',
|
||||
'3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php',
|
||||
'93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php',
|
||||
'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php',
|
||||
);
|
||||
|
||||
@ -70,11 +70,22 @@ class ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$prefixDirsPsr4;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$prefixDirsPsr4;
|
||||
$loader->prefixesPsr0 = ComposerStaticInit02c7a5bb99a87a4c8dbf069d69b1a15c::$prefixesPsr0;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
308
vendor/composer/installed.json
vendored
308
vendor/composer/installed.json
vendored
@ -52,135 +52,19 @@
|
||||
"url"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/event",
|
||||
"version": "3.0.0",
|
||||
"version_normalized": "3.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-event.git",
|
||||
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-event/zipball/831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
||||
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*",
|
||||
"sabre/cs": "~0.0.4"
|
||||
},
|
||||
"time": "2015-11-05 20:14:39",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Sabre\\Event\\": "lib/"
|
||||
},
|
||||
"files": [
|
||||
"lib/coroutine.php",
|
||||
"lib/Loop/functions.php",
|
||||
"lib/Promise/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Evert Pot",
|
||||
"email": "me@evertpot.com",
|
||||
"homepage": "http://evertpot.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "sabre/event is a library for lightweight event-based programming",
|
||||
"homepage": "http://sabre.io/event/",
|
||||
"keywords": [
|
||||
"EventEmitter",
|
||||
"async",
|
||||
"events",
|
||||
"hooks",
|
||||
"plugin",
|
||||
"promise",
|
||||
"signal"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/http",
|
||||
"version": "4.2.1",
|
||||
"version_normalized": "4.2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-http.git",
|
||||
"reference": "2e93bc8321524c67be4ca5b8415daebd4c8bf85e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-http/zipball/2e93bc8321524c67be4ca5b8415daebd4c8bf85e",
|
||||
"reference": "2e93bc8321524c67be4ca5b8415daebd4c8bf85e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.4",
|
||||
"sabre/event": ">=1.0.0,<4.0.0",
|
||||
"sabre/uri": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.3",
|
||||
"sabre/cs": "~0.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": " to make http requests with the Client class"
|
||||
},
|
||||
"time": "2016-01-06 23:00:08",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Sabre\\HTTP\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Evert Pot",
|
||||
"email": "me@evertpot.com",
|
||||
"homepage": "http://evertpot.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "The sabre/http library provides utilities for dealing with http requests and responses. ",
|
||||
"homepage": "https://github.com/fruux/sabre-http",
|
||||
"keywords": [
|
||||
"http"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/xml",
|
||||
"version": "1.4.1",
|
||||
"version_normalized": "1.4.1.0",
|
||||
"version": "1.4.2",
|
||||
"version_normalized": "1.4.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-xml.git",
|
||||
"reference": "59998046db252634259a878baf1af18159f508f3"
|
||||
"reference": "f48d98c22a4a4bef76cabb5968ffaddbb2bb593e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-xml/zipball/59998046db252634259a878baf1af18159f508f3",
|
||||
"reference": "59998046db252634259a878baf1af18159f508f3",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-xml/zipball/f48d98c22a4a4bef76cabb5968ffaddbb2bb593e",
|
||||
"reference": "f48d98c22a4a4bef76cabb5968ffaddbb2bb593e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -195,7 +79,7 @@
|
||||
"phpunit/phpunit": "*",
|
||||
"sabre/cs": "~0.0.2"
|
||||
},
|
||||
"time": "2016-03-12 22:23:16",
|
||||
"time": "2016-05-19 21:56:49",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
@ -331,18 +215,174 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/dav",
|
||||
"version": "3.1.3",
|
||||
"version_normalized": "3.1.3.0",
|
||||
"name": "sabre/event",
|
||||
"version": "3.0.0",
|
||||
"version_normalized": "3.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-dav.git",
|
||||
"reference": "8a266c7b5e140da79529414b9cde2a2d058b536b"
|
||||
"url": "https://github.com/fruux/sabre-event.git",
|
||||
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-dav/zipball/8a266c7b5e140da79529414b9cde2a2d058b536b",
|
||||
"reference": "8a266c7b5e140da79529414b9cde2a2d058b536b",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-event/zipball/831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
||||
"reference": "831d586f5a442dceacdcf5e9c4c36a4db99a3534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "*",
|
||||
"sabre/cs": "~0.0.4"
|
||||
},
|
||||
"time": "2015-11-05 20:14:39",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Sabre\\Event\\": "lib/"
|
||||
},
|
||||
"files": [
|
||||
"lib/coroutine.php",
|
||||
"lib/Loop/functions.php",
|
||||
"lib/Promise/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Evert Pot",
|
||||
"email": "me@evertpot.com",
|
||||
"homepage": "http://evertpot.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "sabre/event is a library for lightweight event-based programming",
|
||||
"homepage": "http://sabre.io/event/",
|
||||
"keywords": [
|
||||
"EventEmitter",
|
||||
"async",
|
||||
"events",
|
||||
"hooks",
|
||||
"plugin",
|
||||
"promise",
|
||||
"signal"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/http",
|
||||
"version": "4.2.1",
|
||||
"version_normalized": "4.2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-http.git",
|
||||
"reference": "2e93bc8321524c67be4ca5b8415daebd4c8bf85e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-http/zipball/2e93bc8321524c67be4ca5b8415daebd4c8bf85e",
|
||||
"reference": "2e93bc8321524c67be4ca5b8415daebd4c8bf85e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.4",
|
||||
"sabre/event": ">=1.0.0,<4.0.0",
|
||||
"sabre/uri": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.3",
|
||||
"sabre/cs": "~0.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-curl": " to make http requests with the Client class"
|
||||
},
|
||||
"time": "2016-01-06 23:00:08",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Sabre\\HTTP\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Evert Pot",
|
||||
"email": "me@evertpot.com",
|
||||
"homepage": "http://evertpot.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "The sabre/http library provides utilities for dealing with http requests and responses. ",
|
||||
"homepage": "https://github.com/fruux/sabre-http",
|
||||
"keywords": [
|
||||
"http"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.0.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
|
||||
"reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
|
||||
"shasum": ""
|
||||
},
|
||||
"time": "2012-12-21 11:40:51",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Psr\\Log\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/dav",
|
||||
"version": "3.2.0",
|
||||
"version_normalized": "3.2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-dav.git",
|
||||
"reference": "5b9737cc2f0182e368d14c80df7f6b2d77dc1457"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-dav/zipball/5b9737cc2f0182e368d14c80df7f6b2d77dc1457",
|
||||
"reference": "5b9737cc2f0182e368d14c80df7f6b2d77dc1457",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -356,14 +396,16 @@
|
||||
"ext-spl": "*",
|
||||
"lib-libxml": ">=2.7.0",
|
||||
"php": ">=5.5.0",
|
||||
"psr/log": "^1.0",
|
||||
"sabre/event": ">=2.0.0, <4.0.0",
|
||||
"sabre/http": "^4.2.1",
|
||||
"sabre/uri": "~1.0",
|
||||
"sabre/vobject": "~4.0",
|
||||
"sabre/xml": "~1.0"
|
||||
"sabre/uri": "^1.0.1",
|
||||
"sabre/vobject": "^4.1.0",
|
||||
"sabre/xml": "^1.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"evert/phpdoc-md": "~0.1.0",
|
||||
"monolog/monolog": "^1.18",
|
||||
"phpunit/phpunit": "> 4.8, <=6.0.0",
|
||||
"sabre/cs": "~0.0.5"
|
||||
},
|
||||
@ -371,7 +413,7 @@
|
||||
"ext-curl": "*",
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"time": "2016-04-07 01:02:57",
|
||||
"time": "2016-06-28 02:44:05",
|
||||
"bin": [
|
||||
"bin/sabredav",
|
||||
"bin/naturalselection"
|
||||
|
1
vendor/psr/log/.gitignore
vendored
Normal file
1
vendor/psr/log/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
vendor
|
19
vendor/psr/log/LICENSE
vendored
Normal file
19
vendor/psr/log/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2012 PHP Framework Interoperability Group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
120
vendor/psr/log/Psr/Log/AbstractLogger.php
vendored
Normal file
120
vendor/psr/log/Psr/Log/AbstractLogger.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* This is a simple Logger implementation that other Loggers can inherit from.
|
||||
*
|
||||
* It simply delegates all log-level-specific methods to the `log` method to
|
||||
* reduce boilerplate code that a simple Logger that does the same thing with
|
||||
* messages regardless of the error level has to implement.
|
||||
*/
|
||||
abstract class AbstractLogger implements LoggerInterface
|
||||
{
|
||||
/**
|
||||
* System is unusable.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function emergency($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::EMERGENCY, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action must be taken immediately.
|
||||
*
|
||||
* Example: Entire website down, database unavailable, etc. This should
|
||||
* trigger the SMS alerts and wake you up.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function alert($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::ALERT, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Critical conditions.
|
||||
*
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function critical($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::CRITICAL, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime errors that do not require immediate action but should typically
|
||||
* be logged and monitored.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function error($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::ERROR, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptional occurrences that are not errors.
|
||||
*
|
||||
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||
* that are not necessarily wrong.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function warning($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::WARNING, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal but significant events.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function notice($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::NOTICE, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interesting events.
|
||||
*
|
||||
* Example: User logs in, SQL logs.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function info($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::INFO, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detailed debug information.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function debug($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::DEBUG, $message, $context);
|
||||
}
|
||||
}
|
7
vendor/psr/log/Psr/Log/InvalidArgumentException.php
vendored
Normal file
7
vendor/psr/log/Psr/Log/InvalidArgumentException.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
{
|
||||
}
|
18
vendor/psr/log/Psr/Log/LogLevel.php
vendored
Normal file
18
vendor/psr/log/Psr/Log/LogLevel.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* Describes log levels
|
||||
*/
|
||||
class LogLevel
|
||||
{
|
||||
const EMERGENCY = 'emergency';
|
||||
const ALERT = 'alert';
|
||||
const CRITICAL = 'critical';
|
||||
const ERROR = 'error';
|
||||
const WARNING = 'warning';
|
||||
const NOTICE = 'notice';
|
||||
const INFO = 'info';
|
||||
const DEBUG = 'debug';
|
||||
}
|
17
vendor/psr/log/Psr/Log/LoggerAwareInterface.php
vendored
Normal file
17
vendor/psr/log/Psr/Log/LoggerAwareInterface.php
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* Describes a logger-aware instance
|
||||
*/
|
||||
interface LoggerAwareInterface
|
||||
{
|
||||
/**
|
||||
* Sets a logger instance on the object
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
* @return null
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger);
|
||||
}
|
22
vendor/psr/log/Psr/Log/LoggerAwareTrait.php
vendored
Normal file
22
vendor/psr/log/Psr/Log/LoggerAwareTrait.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* Basic Implementation of LoggerAwareInterface.
|
||||
*/
|
||||
trait LoggerAwareTrait
|
||||
{
|
||||
/** @var LoggerInterface */
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Sets a logger.
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
}
|
114
vendor/psr/log/Psr/Log/LoggerInterface.php
vendored
Normal file
114
vendor/psr/log/Psr/Log/LoggerInterface.php
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* Describes a logger instance
|
||||
*
|
||||
* The message MUST be a string or object implementing __toString().
|
||||
*
|
||||
* The message MAY contain placeholders in the form: {foo} where foo
|
||||
* will be replaced by the context data in key "foo".
|
||||
*
|
||||
* The context array can contain arbitrary data, the only assumption that
|
||||
* can be made by implementors is that if an Exception instance is given
|
||||
* to produce a stack trace, it MUST be in a key named "exception".
|
||||
*
|
||||
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
|
||||
* for the full interface specification.
|
||||
*/
|
||||
interface LoggerInterface
|
||||
{
|
||||
/**
|
||||
* System is unusable.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function emergency($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Action must be taken immediately.
|
||||
*
|
||||
* Example: Entire website down, database unavailable, etc. This should
|
||||
* trigger the SMS alerts and wake you up.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function alert($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Critical conditions.
|
||||
*
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function critical($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Runtime errors that do not require immediate action but should typically
|
||||
* be logged and monitored.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function error($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Exceptional occurrences that are not errors.
|
||||
*
|
||||
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||
* that are not necessarily wrong.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function warning($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Normal but significant events.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function notice($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Interesting events.
|
||||
*
|
||||
* Example: User logs in, SQL logs.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function info($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Detailed debug information.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function debug($message, array $context = array());
|
||||
|
||||
/**
|
||||
* Logs with an arbitrary level.
|
||||
*
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function log($level, $message, array $context = array());
|
||||
}
|
131
vendor/psr/log/Psr/Log/LoggerTrait.php
vendored
Normal file
131
vendor/psr/log/Psr/Log/LoggerTrait.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* This is a simple Logger trait that classes unable to extend AbstractLogger
|
||||
* (because they extend another class, etc) can include.
|
||||
*
|
||||
* It simply delegates all log-level-specific methods to the `log` method to
|
||||
* reduce boilerplate code that a simple Logger that does the same thing with
|
||||
* messages regardless of the error level has to implement.
|
||||
*/
|
||||
trait LoggerTrait
|
||||
{
|
||||
/**
|
||||
* System is unusable.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function emergency($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::EMERGENCY, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action must be taken immediately.
|
||||
*
|
||||
* Example: Entire website down, database unavailable, etc. This should
|
||||
* trigger the SMS alerts and wake you up.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function alert($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::ALERT, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Critical conditions.
|
||||
*
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function critical($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::CRITICAL, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime errors that do not require immediate action but should typically
|
||||
* be logged and monitored.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function error($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::ERROR, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptional occurrences that are not errors.
|
||||
*
|
||||
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
||||
* that are not necessarily wrong.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function warning($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::WARNING, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal but significant events.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function notice($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::NOTICE, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interesting events.
|
||||
*
|
||||
* Example: User logs in, SQL logs.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function info($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::INFO, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detailed debug information.
|
||||
*
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function debug($message, array $context = array())
|
||||
{
|
||||
$this->log(LogLevel::DEBUG, $message, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs with an arbitrary level.
|
||||
*
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
abstract public function log($level, $message, array $context = array());
|
||||
}
|
27
vendor/psr/log/Psr/Log/NullLogger.php
vendored
Normal file
27
vendor/psr/log/Psr/Log/NullLogger.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log;
|
||||
|
||||
/**
|
||||
* This Logger can be used to avoid conditional log calls
|
||||
*
|
||||
* Logging should always be optional, and if no logger is provided to your
|
||||
* library creating a NullLogger instance to have something to throw logs at
|
||||
* is a good way to avoid littering your code with `if ($this->logger) { }`
|
||||
* blocks.
|
||||
*/
|
||||
class NullLogger extends AbstractLogger
|
||||
{
|
||||
/**
|
||||
* Logs with an arbitrary level.
|
||||
*
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
* @return null
|
||||
*/
|
||||
public function log($level, $message, array $context = array())
|
||||
{
|
||||
// noop
|
||||
}
|
||||
}
|
116
vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
vendored
Normal file
116
vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Psr\Log\Test;
|
||||
|
||||
use Psr\Log\LogLevel;
|
||||
|
||||
/**
|
||||
* Provides a base test class for ensuring compliance with the LoggerInterface
|
||||
*
|
||||
* Implementors can extend the class and implement abstract methods to run this as part of their test suite
|
||||
*/
|
||||
abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
abstract function getLogger();
|
||||
|
||||
/**
|
||||
* This must return the log messages in order with a simple formatting: "<LOG LEVEL> <MESSAGE>"
|
||||
*
|
||||
* Example ->error('Foo') would yield "error Foo"
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract function getLogs();
|
||||
|
||||
public function testImplements()
|
||||
{
|
||||
$this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideLevelsAndMessages
|
||||
*/
|
||||
public function testLogsAtAllLevels($level, $message)
|
||||
{
|
||||
$logger = $this->getLogger();
|
||||
$logger->{$level}($message, array('user' => 'Bob'));
|
||||
$logger->log($level, $message, array('user' => 'Bob'));
|
||||
|
||||
$expected = array(
|
||||
$level.' message of level '.$level.' with context: Bob',
|
||||
$level.' message of level '.$level.' with context: Bob',
|
||||
);
|
||||
$this->assertEquals($expected, $this->getLogs());
|
||||
}
|
||||
|
||||
public function provideLevelsAndMessages()
|
||||
{
|
||||
return array(
|
||||
LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
|
||||
LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
|
||||
LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
|
||||
LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
|
||||
LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
|
||||
LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
|
||||
LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
|
||||
LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Psr\Log\InvalidArgumentException
|
||||
*/
|
||||
public function testThrowsOnInvalidLevel()
|
||||
{
|
||||
$logger = $this->getLogger();
|
||||
$logger->log('invalid level', 'Foo');
|
||||
}
|
||||
|
||||
public function testContextReplacement()
|
||||
{
|
||||
$logger = $this->getLogger();
|
||||
$logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
|
||||
|
||||
$expected = array('info {Message {nothing} Bob Bar a}');
|
||||
$this->assertEquals($expected, $this->getLogs());
|
||||
}
|
||||
|
||||
public function testObjectCastToString()
|
||||
{
|
||||
$dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
|
||||
$dummy->expects($this->once())
|
||||
->method('__toString')
|
||||
->will($this->returnValue('DUMMY'));
|
||||
|
||||
$this->getLogger()->warning($dummy);
|
||||
}
|
||||
|
||||
public function testContextCanContainAnything()
|
||||
{
|
||||
$context = array(
|
||||
'bool' => true,
|
||||
'null' => null,
|
||||
'string' => 'Foo',
|
||||
'int' => 0,
|
||||
'float' => 0.5,
|
||||
'nested' => array('with object' => new DummyTest),
|
||||
'object' => new \DateTime,
|
||||
'resource' => fopen('php://memory', 'r'),
|
||||
);
|
||||
|
||||
$this->getLogger()->warning('Crazy context data', $context);
|
||||
}
|
||||
|
||||
public function testContextExceptionKeyCanBeExceptionOrOtherValues()
|
||||
{
|
||||
$this->getLogger()->warning('Random message', array('exception' => 'oops'));
|
||||
$this->getLogger()->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
|
||||
}
|
||||
}
|
||||
|
||||
class DummyTest
|
||||
{
|
||||
}
|
45
vendor/psr/log/README.md
vendored
Normal file
45
vendor/psr/log/README.md
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
PSR Log
|
||||
=======
|
||||
|
||||
This repository holds all interfaces/classes/traits related to
|
||||
[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).
|
||||
|
||||
Note that this is not a logger of its own. It is merely an interface that
|
||||
describes a logger. See the specification for more details.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
If you need a logger, you can use the interface like this:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Foo
|
||||
{
|
||||
private $logger;
|
||||
|
||||
public function __construct(LoggerInterface $logger = null)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function doSomething()
|
||||
{
|
||||
if ($this->logger) {
|
||||
$this->logger->info('Doing work');
|
||||
}
|
||||
|
||||
// do something useful
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can then pick one of the implementations of the interface to get a logger.
|
||||
|
||||
If you want to implement the interface, you can require this package and
|
||||
implement `Psr\Log\LoggerInterface` in your code. Please read the
|
||||
[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
|
||||
for details.
|
24
vendor/sabre/dav/.travis.yml
vendored
24
vendor/sabre/dav/.travis.yml
vendored
@ -3,12 +3,6 @@ php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
|
||||
env:
|
||||
matrix:
|
||||
@ -17,17 +11,25 @@ env:
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
|
||||
sudo: false
|
||||
|
||||
cache: vendor
|
||||
|
||||
before_script:
|
||||
- mysql -e 'create database sabredav'
|
||||
- mysql -e 'create database sabredav_test'
|
||||
- psql -c "create database sabredav_test" -U postgres
|
||||
- psql -c "create user sabredav with PASSWORD 'sabredav';GRANT ALL PRIVILEGES ON DATABASE sabredav_test TO sabredav" -U postgres
|
||||
- phpenv config-rm xdebug.ini; true
|
||||
# - composer self-update
|
||||
- composer update --prefer-source $LOWEST_DEPS
|
||||
- composer update --prefer-dist $LOWEST_DEPS
|
||||
|
||||
# addons:
|
||||
# postgresql: "9.5"
|
||||
|
||||
script:
|
||||
- ./bin/phpunit --configuration tests/phpunit.xml $TEST_DEPS
|
||||
- ./bin/phpunit --configuration tests/phpunit.xml.dist $TEST_DEPS
|
||||
- ./bin/sabre-cs-fixer fix lib/ --dry-run --diff
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
100
vendor/sabre/dav/CHANGELOG.md
vendored
100
vendor/sabre/dav/CHANGELOG.md
vendored
@ -1,6 +1,106 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
3.2.0 (2016-06-27)
|
||||
------------------
|
||||
|
||||
* The default ACL rules allow an unauthenticated user to read information
|
||||
about nodes that don't have their own ACL defined. This was a security
|
||||
problem.
|
||||
* The zip release ships with [sabre/vobject 4.1.0][vobj],
|
||||
[sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt],
|
||||
[sabre/uri 1.1.0][uri] and [sabre/xml 1.4.2][xml].
|
||||
|
||||
|
||||
3.2.0-beta1 (2016-05-20)
|
||||
------------------------
|
||||
|
||||
* #833: Calendars throw exceptions when the sharing plugin is not enabled.
|
||||
* #834: Return vCards exactly as they were stored if we don't need to convert
|
||||
in between versions.
|
||||
* The zip release ships with [sabre/vobject 4.1.0][vobj],
|
||||
[sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt],
|
||||
[sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml].
|
||||
|
||||
|
||||
3.2.0-alpha1 (2016-05-09)
|
||||
-------------------------
|
||||
|
||||
* Database changes for CalDAV. If you are using the CalDAV PDO backends, you
|
||||
must migrate. Run `./bin/migrateto32.php` for more info.
|
||||
* Support for WebDAV Resource Sharing, an upcoming standard.
|
||||
* Added support for sharing in the CalDAV PDO backend! Users can now invite
|
||||
others to their calendar and give them read/read-write access!
|
||||
* #397: Support for PSR-3. You can now log exceptions with your favourite
|
||||
psr3-compatible logging tool.
|
||||
* #825: Actual proper, tested support for PostgreSQL. We require version 9.5.
|
||||
* Removed database migration script for sabre/dav 1.7. To update from that
|
||||
version you now first need to update to sabre/dav 3.1.
|
||||
* Removed deprecated function: `Sabre\DAV\Auth\Plugin::getCurrentUser()`.
|
||||
* #774: Fixes for getting free disk space on Windows.
|
||||
* #803: Major changes in the sharing API. If you were using an old sabre/dav
|
||||
sharing api, head to the website for more detailed migration notes.
|
||||
* #657: Support for optional auth using `{DAV:}unauthorized` and `{DAV:}all`
|
||||
privileges. This allows you to assign a privilege to a resource, allowing
|
||||
non-authenticated users to access it. For instance, this could allow you
|
||||
to create a public read-only collection.
|
||||
* #812 #814: ICS/VCF exporter now includes a more useful filename in its
|
||||
`Content-Disposition` header. (@Xenopathic).
|
||||
* #801: BC break: If you were using the `Href` object before, it's behavior
|
||||
now changed a bit, and `LocalHref` was added to replace the old, default
|
||||
behavior of `Href`. See the migration doc for more info.
|
||||
* Removed `Sabre\DAVACL\Plugin::$allowAccessToNodesWithoutACL` setting.
|
||||
Instead, you can provide a set of default ACL rules with
|
||||
`Sabre\DAVACL\Plugin::setDefaultAcl()`.
|
||||
* Introduced `Sabre\DAVACL\ACLTrait` which contains a default implementation
|
||||
of `Sabre\DAV\IACL` with some sane defaults. We're using this trait all over
|
||||
the place now, reducing the amount of boilerplate.
|
||||
* Plugins can now control the "Supported Privilege Set".
|
||||
* Added Sharing, ICSExport and VCFExport plugins to `groupwareserver.php`
|
||||
example.
|
||||
* The `{DAV:}all` privilege is now no longer abstract, so it can be assigned
|
||||
directly. We're using the `{DAV:}all` privilege now in a lot of cases where
|
||||
we before assigned both `{DAV:}read` and `{DAV:}write`.
|
||||
* Resources that are not collections no longer support the `{DAV:}bind` and
|
||||
`{DAV:}unbind` privileges.
|
||||
* Corrected the CalDAV-scheduling related privileges.
|
||||
* Doing an `UNLOCK` no longer requires the `{DAV:}write-content` privilege.
|
||||
* Added a new `getPrincipalByUri` plugin event. Allowing plugins to request
|
||||
quickly where a principal lives on a server.
|
||||
* Renamed `phpunit.xml` to `phpunit.xml.dist` to make local modifications easy.
|
||||
* Functionality from `IShareableCalendar` is merged into `ISharedCalendar`.
|
||||
* #751: Fixed XML responses from failing `MKCOL` requests.
|
||||
* #600: Support for `principal-match` ACL `REPORT`.
|
||||
* #599: Support for `acl-principal-prop-set` ACL `REPORT`.
|
||||
* #798: Added an index on `firstoccurence` field in MySQL CalDAV backend. This
|
||||
should speed up common calendar-query requests.
|
||||
* #759: DAV\Client is now able to actually correctly resolve relative urls.
|
||||
* #671: We are no longer checking the `read-free-busy` privilege on individual
|
||||
calendars during freebusy operations in the scheduling plugin. Instead, we
|
||||
check the `schedule-query-freebusy` privilege on the target users' inbox,
|
||||
which validates access for the entire account, per the spec.
|
||||
* The zip release ships with [sabre/vobject 4.1.0][vobj],
|
||||
[sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt],
|
||||
[sabre/uri 1.1.0][uri] and [sabre/xml 1.4.1][xml].
|
||||
|
||||
|
||||
3.1.5 (????-??-??)
|
||||
------------------
|
||||
|
||||
* Fixed: Creating a new calendar on some MySQL configurations caused an error.
|
||||
|
||||
|
||||
3.1.4 (2016-05-28)
|
||||
------------------
|
||||
|
||||
* #834: Backport from `master`: Return vCards exactly as they were stored if
|
||||
we don't need to convert in between versions. This should speed up many
|
||||
large addressbook syncs sometimes up to 50%.
|
||||
* The zip release ships with [sabre/vobject 4.1.0][vobj],
|
||||
[sabre/http 4.2.1][http], [sabre/event 3.0.0][evnt],
|
||||
[sabre/uri 1.1.0][uri] and [sabre/xml 1.4.2][xml].
|
||||
|
||||
|
||||
3.1.3 (2016-04-06)
|
||||
------------------
|
||||
|
||||
|
13
vendor/sabre/dav/README.md
vendored
13
vendor/sabre/dav/README.md
vendored
@ -1,10 +1,10 @@
|
||||
 SabreDAV
|
||||
======================================================
|
||||
 sabre/dav
|
||||
=======================================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
SabreDAV is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers.
|
||||
sabre/dav is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers.
|
||||
|
||||
Full documentation can be found on the website:
|
||||
|
||||
@ -16,6 +16,7 @@ Build status
|
||||
| branch | status | minimum PHP version |
|
||||
| ------------ | ------ | ------------------- |
|
||||
| master | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 |
|
||||
| 3.1 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.5 |
|
||||
| 3.0 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 |
|
||||
| 2.1 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 |
|
||||
| 2.0 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.4 |
|
||||
@ -23,6 +24,12 @@ Build status
|
||||
| 1.7 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 |
|
||||
| 1.6 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 |
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
* [Introduction](http://sabre.io/dav/).
|
||||
* [Installation](http://sabre.io/dav/install/).
|
||||
|
||||
Made at fruux
|
||||
-------------
|
||||
|
||||
|
2
vendor/sabre/dav/bin/build.php
vendored
Executable file → Normal file
2
vendor/sabre/dav/bin/build.php
vendored
Executable file → Normal file
@ -110,7 +110,7 @@ function test() {
|
||||
|
||||
echo " Running all unittests.\n";
|
||||
echo " This may take a while.\n\n";
|
||||
system(__DIR__ . '/phpunit --configuration ' . $baseDir . '/tests/phpunit.xml --stop-on-failure', $code);
|
||||
system(__DIR__ . '/phpunit --configuration ' . $baseDir . '/tests/phpunit.xml.dist --stop-on-failure', $code);
|
||||
if ($code != 0) {
|
||||
echo "PHPUnit reported error code $code\n";
|
||||
die(1);
|
||||
|
0
vendor/sabre/dav/bin/googlecode_upload.py
vendored
Executable file → Normal file
0
vendor/sabre/dav/bin/googlecode_upload.py
vendored
Executable file → Normal file
284
vendor/sabre/dav/bin/migrateto17.php
vendored
284
vendor/sabre/dav/bin/migrateto17.php
vendored
@ -1,284 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
echo "SabreDAV migrate script for version 1.7\n";
|
||||
|
||||
if ($argc < 2) {
|
||||
|
||||
echo <<<HELLO
|
||||
|
||||
This script help you migrate from a pre-1.7 database to 1.7 and later\n
|
||||
Both the 'calendarobjects' and 'calendars' tables will be upgraded.
|
||||
|
||||
If you do not have this table, or don't use the default PDO CalDAV backend
|
||||
it's pointless to run this script.
|
||||
|
||||
Keep in mind that some processing will be done on every single record of this
|
||||
table and in addition, ALTER TABLE commands will be executed.
|
||||
If you have a large calendarobjects table, this may mean that this process
|
||||
takes a while.
|
||||
|
||||
Usage:
|
||||
|
||||
php {$argv[0]} [pdo-dsn] [username] [password]
|
||||
|
||||
For example:
|
||||
|
||||
php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password
|
||||
php {$argv[0]} sqlite:data/sabredav.db
|
||||
|
||||
HELLO;
|
||||
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
// There's a bunch of places where the autoloader could be, so we'll try all of
|
||||
// them.
|
||||
$paths = [
|
||||
__DIR__ . '/../vendor/autoload.php',
|
||||
__DIR__ . '/../../../autoload.php',
|
||||
];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$dsn = $argv[1];
|
||||
$user = isset($argv[2]) ? $argv[2] : null;
|
||||
$pass = isset($argv[3]) ? $argv[3] : null;
|
||||
|
||||
echo "Connecting to database: " . $dsn . "\n";
|
||||
|
||||
$pdo = new PDO($dsn, $user, $pass);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
|
||||
echo "Validating existing table layout\n";
|
||||
|
||||
// The only cross-db way to do this, is to just fetch a single record.
|
||||
$row = $pdo->query("SELECT * FROM calendarobjects LIMIT 1")->fetch();
|
||||
|
||||
if (!$row) {
|
||||
echo "Error: This database did not have any records in the calendarobjects table, you should just recreate the table.\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
'id',
|
||||
'calendardata',
|
||||
'uri',
|
||||
'calendarid',
|
||||
'lastmodified',
|
||||
];
|
||||
|
||||
foreach ($requiredFields as $requiredField) {
|
||||
if (!array_key_exists($requiredField, $row)) {
|
||||
echo "Error: The current 'calendarobjects' table was missing a field we expected to exist.\n";
|
||||
echo "For safety reasons, this process is stopped.\n";
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
$fields17 = [
|
||||
'etag',
|
||||
'size',
|
||||
'componenttype',
|
||||
'firstoccurence',
|
||||
'lastoccurence',
|
||||
];
|
||||
|
||||
$found = 0;
|
||||
foreach ($fields17 as $field) {
|
||||
if (array_key_exists($field, $row)) {
|
||||
$found++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found === 0) {
|
||||
echo "The database had the 1.6 schema. Table will now be altered.\n";
|
||||
echo "This may take some time for large tables\n";
|
||||
|
||||
switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
|
||||
case 'mysql' :
|
||||
|
||||
$pdo->exec(<<<SQL
|
||||
ALTER TABLE calendarobjects
|
||||
ADD etag VARCHAR(32),
|
||||
ADD size INT(11) UNSIGNED,
|
||||
ADD componenttype VARCHAR(8),
|
||||
ADD firstoccurence INT(11) UNSIGNED,
|
||||
ADD lastoccurence INT(11) UNSIGNED
|
||||
SQL
|
||||
);
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD etag text');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD size integer');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD componenttype TEXT');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD firstoccurence integer');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD lastoccurence integer');
|
||||
break;
|
||||
|
||||
default :
|
||||
die('This upgrade script does not support this driver (' . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . ")\n");
|
||||
|
||||
}
|
||||
echo "Database schema upgraded.\n";
|
||||
|
||||
} elseif ($found === 5) {
|
||||
|
||||
echo "Database already had the 1.7 schema\n";
|
||||
|
||||
} else {
|
||||
|
||||
echo "The database had $found out of 5 from the changes for 1.7. This is scary and unusual, so we have to abort.\n";
|
||||
echo "You can manually try to upgrade the schema, and then run this script again.\n";
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
echo "Now, we need to parse every record and pull out some information.\n";
|
||||
|
||||
$result = $pdo->query('SELECT id, calendardata FROM calendarobjects');
|
||||
$stmt = $pdo->prepare('UPDATE calendarobjects SET etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ? WHERE id = ?');
|
||||
|
||||
echo "Total records found: " . $result->rowCount() . "\n";
|
||||
$done = 0;
|
||||
$total = $result->rowCount();
|
||||
while ($row = $result->fetch()) {
|
||||
|
||||
try {
|
||||
$newData = getDenormalizedData($row['calendardata']);
|
||||
} catch (Exception $e) {
|
||||
echo "===\nException caught will trying to parser calendarobject.\n";
|
||||
echo "Error message: " . $e->getMessage() . "\n";
|
||||
echo "Record id: " . $row['id'] . "\n";
|
||||
echo "This record is ignored, you should inspect it to see if there's anything wrong.\n===\n";
|
||||
continue;
|
||||
}
|
||||
$stmt->execute([
|
||||
$newData['etag'],
|
||||
$newData['size'],
|
||||
$newData['componentType'],
|
||||
$newData['firstOccurence'],
|
||||
$newData['lastOccurence'],
|
||||
$row['id'],
|
||||
]);
|
||||
$done++;
|
||||
|
||||
if ($done % 500 === 0) {
|
||||
echo "Completed: $done / $total\n";
|
||||
}
|
||||
}
|
||||
echo "Completed: $done / $total\n";
|
||||
|
||||
echo "Checking the calendars table needs changes.\n";
|
||||
$row = $pdo->query("SELECT * FROM calendars LIMIT 1")->fetch();
|
||||
|
||||
if (array_key_exists('transparent', $row)) {
|
||||
|
||||
echo "The calendars table is already up to date\n";
|
||||
|
||||
} else {
|
||||
|
||||
echo "Adding the 'transparent' field to the calendars table\n";
|
||||
|
||||
switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
|
||||
case 'mysql' :
|
||||
$pdo->exec("ALTER TABLE calendars ADD transparent TINYINT(1) NOT NULL DEFAULT '0'");
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec("ALTER TABLE calendars ADD transparent bool");
|
||||
break;
|
||||
|
||||
default :
|
||||
die('This upgrade script does not support this driver (' . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . ")\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo "Process completed!\n";
|
||||
|
||||
/**
|
||||
* Parses some information from calendar objects, used for optimized
|
||||
* calendar-queries.
|
||||
*
|
||||
* Blantently copied from Sabre\CalDAV\Backend\PDO
|
||||
*
|
||||
* Returns an array with the following keys:
|
||||
* * etag
|
||||
* * size
|
||||
* * componentType
|
||||
* * firstOccurence
|
||||
* * lastOccurence
|
||||
*
|
||||
* @param string $calendarData
|
||||
* @return array
|
||||
*/
|
||||
function getDenormalizedData($calendarData) {
|
||||
|
||||
$vObject = \Sabre\VObject\Reader::read($calendarData);
|
||||
$componentType = null;
|
||||
$component = null;
|
||||
$firstOccurence = null;
|
||||
$lastOccurence = null;
|
||||
foreach ($vObject->getComponents() as $component) {
|
||||
if ($component->name !== 'VTIMEZONE') {
|
||||
$componentType = $component->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$componentType) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
|
||||
}
|
||||
if ($componentType === 'VEVENT') {
|
||||
$firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
|
||||
// Finding the last occurence is a bit harder
|
||||
if (!isset($component->RRULE)) {
|
||||
if (isset($component->DTEND)) {
|
||||
$lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
|
||||
} elseif (isset($component->DURATION)) {
|
||||
$endDate = clone $component->DTSTART->getDateTime();
|
||||
$endDate->add(\Sabre\VObject\DateTimeParser::parse($component->DURATION->value));
|
||||
$lastOccurence = $endDate->getTimeStamp();
|
||||
} elseif (!$component->DTSTART->hasTime()) {
|
||||
$endDate = clone $component->DTSTART->getDateTime();
|
||||
$endDate->modify('+1 day');
|
||||
$lastOccurence = $endDate->getTimeStamp();
|
||||
} else {
|
||||
$lastOccurence = $firstOccurence;
|
||||
}
|
||||
} else {
|
||||
$it = new \Sabre\VObject\Recur\EventIterator($vObject, (string)$component->UID);
|
||||
$maxDate = new DateTime(\Sabre\CalDAV\Backend\PDO::MAX_DATE);
|
||||
if ($it->isInfinite()) {
|
||||
$lastOccurence = $maxDate->getTimeStamp();
|
||||
} else {
|
||||
$end = $it->getDtEnd();
|
||||
while ($it->valid() && $end < $maxDate) {
|
||||
$end = $it->getDtEnd();
|
||||
$it->next();
|
||||
|
||||
}
|
||||
$lastOccurence = $end->getTimeStamp();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'etag' => md5($calendarData),
|
||||
'size' => strlen($calendarData),
|
||||
'componentType' => $componentType,
|
||||
'firstOccurence' => $firstOccurence,
|
||||
'lastOccurence' => $lastOccurence,
|
||||
];
|
||||
|
||||
}
|
0
vendor/sabre/dav/bin/migrateto20.php
vendored
Executable file → Normal file
0
vendor/sabre/dav/bin/migrateto20.php
vendored
Executable file → Normal file
4
vendor/sabre/dav/bin/migrateto21.php
vendored
Executable file → Normal file
4
vendor/sabre/dav/bin/migrateto21.php
vendored
Executable file → Normal file
@ -169,10 +169,6 @@ switch ($driver) {
|
||||
)
|
||||
');
|
||||
break;
|
||||
$pdo->exec('
|
||||
CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri);
|
||||
');
|
||||
break;
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
|
0
vendor/sabre/dav/bin/migrateto30.php
vendored
Executable file → Normal file
0
vendor/sabre/dav/bin/migrateto30.php
vendored
Executable file → Normal file
268
vendor/sabre/dav/bin/migrateto32.php
vendored
Normal file
268
vendor/sabre/dav/bin/migrateto32.php
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
echo "SabreDAV migrate script for version 3.2\n";
|
||||
|
||||
if ($argc < 2) {
|
||||
|
||||
echo <<<HELLO
|
||||
|
||||
This script help you migrate from a 3.1 database to 3.2 and later
|
||||
|
||||
Changes:
|
||||
* Created a new calendarinstances table to support calendar sharing.
|
||||
* Remove a lot of columns from calendars.
|
||||
|
||||
Keep in mind that ALTER TABLE commands will be executed. If you have a large
|
||||
dataset this may mean that this process takes a while.
|
||||
|
||||
Make a back-up first. This script has been tested, but the amount of
|
||||
potential variants are extremely high, so it's impossible to deal with every
|
||||
possible situation.
|
||||
|
||||
In the worst case, you will lose all your data. This is not an overstatement.
|
||||
|
||||
Lastly, if you are upgrading from an older version than 3.1, make sure you run
|
||||
the earlier migration script first. Migration scripts must be ran in order.
|
||||
|
||||
Usage:
|
||||
|
||||
php {$argv[0]} [pdo-dsn] [username] [password]
|
||||
|
||||
For example:
|
||||
|
||||
php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password
|
||||
php {$argv[0]} sqlite:data/sabredav.db
|
||||
|
||||
HELLO;
|
||||
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
// There's a bunch of places where the autoloader could be, so we'll try all of
|
||||
// them.
|
||||
$paths = [
|
||||
__DIR__ . '/../vendor/autoload.php',
|
||||
__DIR__ . '/../../../autoload.php',
|
||||
];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$dsn = $argv[1];
|
||||
$user = isset($argv[2]) ? $argv[2] : null;
|
||||
$pass = isset($argv[3]) ? $argv[3] : null;
|
||||
|
||||
$backupPostfix = time();
|
||||
|
||||
echo "Connecting to database: " . $dsn . "\n";
|
||||
|
||||
$pdo = new PDO($dsn, $user, $pass);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
|
||||
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||
|
||||
switch ($driver) {
|
||||
|
||||
case 'mysql' :
|
||||
echo "Detected MySQL.\n";
|
||||
break;
|
||||
case 'sqlite' :
|
||||
echo "Detected SQLite.\n";
|
||||
break;
|
||||
default :
|
||||
echo "Error: unsupported driver: " . $driver . "\n";
|
||||
die(-1);
|
||||
}
|
||||
|
||||
echo "Creating 'calendarinstances'\n";
|
||||
$addValueType = false;
|
||||
try {
|
||||
$result = $pdo->query('SELECT * FROM calendarinstances LIMIT 1');
|
||||
$result->fetch(\PDO::FETCH_ASSOC);
|
||||
echo "calendarinstances exists. Assuming this part of the migration has already been done.\n";
|
||||
} catch (Exception $e) {
|
||||
echo "calendarinstances does not yet exist. Creating table and migrating data.\n";
|
||||
|
||||
switch ($driver) {
|
||||
case 'mysql' :
|
||||
$pdo->exec(<<<SQL
|
||||
CREATE TABLE calendarinstances (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
calendarid INTEGER UNSIGNED NOT NULL,
|
||||
principaluri VARBINARY(100),
|
||||
access TINYINT(1) NOT NULL DEFAULT '1' COMMENT '1 = owner, 2 = read, 3 = readwrite',
|
||||
displayname VARCHAR(100),
|
||||
uri VARBINARY(200),
|
||||
description TEXT,
|
||||
calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
calendarcolor VARBINARY(10),
|
||||
timezone TEXT,
|
||||
transparent TINYINT(1) NOT NULL DEFAULT '0',
|
||||
share_href VARBINARY(100),
|
||||
share_displayname VARCHAR(100),
|
||||
share_invitestatus TINYINT(1) NOT NULL DEFAULT '2' COMMENT '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid',
|
||||
UNIQUE(principaluri, uri),
|
||||
UNIQUE(calendarid, principaluri),
|
||||
UNIQUE(calendarid, share_href)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
SQL
|
||||
);
|
||||
$pdo->exec("
|
||||
INSERT INTO calendarinstances
|
||||
(
|
||||
calendarid,
|
||||
principaluri,
|
||||
access,
|
||||
displayname,
|
||||
uri,
|
||||
description,
|
||||
calendarorder,
|
||||
calendarcolor,
|
||||
transparent
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
principaluri,
|
||||
1,
|
||||
displayname,
|
||||
uri,
|
||||
description,
|
||||
calendarorder,
|
||||
calendarcolor,
|
||||
transparent
|
||||
FROM calendars
|
||||
");
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec(<<<SQL
|
||||
CREATE TABLE calendarinstances (
|
||||
id integer primary key asc NOT NULL,
|
||||
calendarid integer,
|
||||
principaluri text,
|
||||
access integer COMMENT '1 = owner, 2 = read, 3 = readwrite' NOT NULL DEFAULT '1',
|
||||
displayname text,
|
||||
uri text NOT NULL,
|
||||
description text,
|
||||
calendarorder integer,
|
||||
calendarcolor text,
|
||||
timezone text,
|
||||
transparent bool,
|
||||
share_href text,
|
||||
share_displayname text,
|
||||
share_invitestatus integer DEFAULT '2',
|
||||
UNIQUE (principaluri, uri),
|
||||
UNIQUE (calendarid, principaluri),
|
||||
UNIQUE (calendarid, share_href)
|
||||
);
|
||||
SQL
|
||||
);
|
||||
$pdo->exec("
|
||||
INSERT INTO calendarinstances
|
||||
(
|
||||
calendarid,
|
||||
principaluri,
|
||||
access,
|
||||
displayname,
|
||||
uri,
|
||||
description,
|
||||
calendarorder,
|
||||
calendarcolor,
|
||||
transparent
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
principaluri,
|
||||
1,
|
||||
displayname,
|
||||
uri,
|
||||
description,
|
||||
calendarorder,
|
||||
calendarcolor,
|
||||
transparent
|
||||
FROM calendars
|
||||
");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
try {
|
||||
$result = $pdo->query('SELECT * FROM calendars LIMIT 1');
|
||||
$row = $result->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$row) {
|
||||
echo "Source table is empty.\n";
|
||||
$migrateCalendars = true;
|
||||
}
|
||||
|
||||
$columnCount = count($row);
|
||||
if ($columnCount === 3) {
|
||||
echo "The calendars table has 3 columns already. Assuming this part of the migration was already done.\n";
|
||||
$migrateCalendars = false;
|
||||
} else {
|
||||
echo "The calendars table has " . $columnCount . " columns.\n";
|
||||
$migrateCalendars = true;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "calendars table does not exist. This is a major problem. Exiting.\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ($migrateCalendars) {
|
||||
|
||||
$calendarBackup = 'calendars_3_1_' . $backupPostfix;
|
||||
echo "Backing up 'calendars' to '", $calendarBackup, "'\n";
|
||||
|
||||
switch ($driver) {
|
||||
case 'mysql' :
|
||||
$pdo->exec('RENAME TABLE calendars TO ' . $calendarBackup);
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec('ALTER TABLE calendars RENAME TO ' . $calendarBackup);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
echo "Creating new calendars table.\n";
|
||||
switch ($driver) {
|
||||
case 'mysql' :
|
||||
$pdo->exec(<<<SQL
|
||||
CREATE TABLE calendars (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1',
|
||||
components VARBINARY(21)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
SQL
|
||||
);
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec(<<<SQL
|
||||
CREATE TABLE calendars (
|
||||
id integer primary key asc NOT NULL,
|
||||
synctoken integer DEFAULT 1 NOT NULL,
|
||||
components text NOT NULL
|
||||
);
|
||||
SQL
|
||||
);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
echo "Migrating data from old to new table\n";
|
||||
|
||||
$pdo->exec(<<<SQL
|
||||
INSERT INTO calendars (id, synctoken, components) SELECT id, synctoken, COALESCE(components,"VEVENT,VTODO,VJOURNAL") as components FROM $calendarBackup
|
||||
SQL
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
echo "Upgrade to 3.2 schema completed.\n";
|
2
vendor/sabre/dav/bin/naturalselection
vendored
2
vendor/sabre/dav/bin/naturalselection
vendored
@ -107,7 +107,7 @@ def main():
|
||||
parser.add_option(
|
||||
'-m', '--min-erase',
|
||||
help="Minimum number of bytes to erase when the threshold is reached. " +
|
||||
"Setting this option higher will reduce the amount of times the cache directory will need to be scanned. " +
|
||||
"Setting this option higher will reduce the number of times the cache directory will need to be scanned. " +
|
||||
"(the default is 1073741824, which is 1GB.)",
|
||||
type="int",
|
||||
dest="min_erase",
|
||||
|
0
vendor/sabre/dav/bin/sabredav.php
vendored
Executable file → Normal file
0
vendor/sabre/dav/bin/sabredav.php
vendored
Executable file → Normal file
57
vendor/sabre/dav/examples/addressbookserver.php
vendored
57
vendor/sabre/dav/examples/addressbookserver.php
vendored
@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
Addressbook/CardDAV server example
|
||||
|
||||
This server features CardDAV support
|
||||
|
||||
*/
|
||||
|
||||
// settings
|
||||
date_default_timezone_set('Canada/Eastern');
|
||||
|
||||
// Make sure this setting is turned on and reflect the root url for your WebDAV server.
|
||||
// This can be for example the root / or a complete path to your server script
|
||||
$baseUri = '/';
|
||||
|
||||
/* Database */
|
||||
$pdo = new PDO('sqlite:data/db.sqlite');
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
//Mapping PHP errors to exceptions
|
||||
function exception_error_handler($errno, $errstr, $errfile, $errline) {
|
||||
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
}
|
||||
set_error_handler("exception_error_handler");
|
||||
|
||||
// Autoloader
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Backends
|
||||
$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
|
||||
$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo);
|
||||
$carddavBackend = new Sabre\CardDAV\Backend\PDO($pdo);
|
||||
//$caldavBackend = new Sabre\CalDAV\Backend\PDO($pdo);
|
||||
|
||||
// Setting up the directory tree //
|
||||
$nodes = [
|
||||
new Sabre\DAVACL\PrincipalCollection($principalBackend),
|
||||
// new Sabre\CalDAV\CalendarRoot($authBackend, $caldavBackend),
|
||||
new Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend),
|
||||
];
|
||||
|
||||
// The object tree needs in turn to be passed to the server class
|
||||
$server = new Sabre\DAV\Server($nodes);
|
||||
$server->setBaseUri($baseUri);
|
||||
|
||||
// Plugins
|
||||
$server->addPlugin(new Sabre\DAV\Auth\Plugin($authBackend));
|
||||
$server->addPlugin(new Sabre\DAV\Browser\Plugin());
|
||||
//$server->addPlugin(new Sabre\CalDAV\Plugin());
|
||||
$server->addPlugin(new Sabre\CardDAV\Plugin());
|
||||
$server->addPlugin(new Sabre\DAVACL\Plugin());
|
||||
$server->addPlugin(new Sabre\DAV\Sync\Plugin());
|
||||
|
||||
// And off we go!
|
||||
$server->exec();
|
@ -1,28 +0,0 @@
|
||||
CREATE TABLE addressbooks (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARBINARY(255),
|
||||
displayname VARCHAR(255),
|
||||
uri VARBINARY(200),
|
||||
description TEXT,
|
||||
synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1',
|
||||
UNIQUE(principaluri(100), uri(100))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE cards (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
addressbookid INT(11) UNSIGNED NOT NULL,
|
||||
carddata MEDIUMBLOB,
|
||||
uri VARBINARY(200),
|
||||
lastmodified INT(11) UNSIGNED,
|
||||
etag VARBINARY(32),
|
||||
size INT(11) UNSIGNED NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE addressbookchanges (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
uri VARBINARY(200) NOT NULL,
|
||||
synctoken INT(11) UNSIGNED NOT NULL,
|
||||
addressbookid INT(11) UNSIGNED NOT NULL,
|
||||
operation TINYINT(1) NOT NULL,
|
||||
INDEX addressbookid_synctoken (addressbookid, synctoken)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
@ -1,64 +0,0 @@
|
||||
CREATE TABLE calendarobjects (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
calendardata MEDIUMBLOB,
|
||||
uri VARBINARY(200),
|
||||
calendarid INTEGER UNSIGNED NOT NULL,
|
||||
lastmodified INT(11) UNSIGNED,
|
||||
etag VARBINARY(32),
|
||||
size INT(11) UNSIGNED NOT NULL,
|
||||
componenttype VARBINARY(8),
|
||||
firstoccurence INT(11) UNSIGNED,
|
||||
lastoccurence INT(11) UNSIGNED,
|
||||
uid VARBINARY(200),
|
||||
UNIQUE(calendarid, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARBINARY(100),
|
||||
displayname VARCHAR(100),
|
||||
uri VARBINARY(200),
|
||||
synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1',
|
||||
description TEXT,
|
||||
calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
calendarcolor VARBINARY(10),
|
||||
timezone TEXT,
|
||||
components VARBINARY(21),
|
||||
transparent TINYINT(1) NOT NULL DEFAULT '0',
|
||||
UNIQUE(principaluri, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE calendarchanges (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
uri VARBINARY(200) NOT NULL,
|
||||
synctoken INT(11) UNSIGNED NOT NULL,
|
||||
calendarid INT(11) UNSIGNED NOT NULL,
|
||||
operation TINYINT(1) NOT NULL,
|
||||
INDEX calendarid_synctoken (calendarid, synctoken)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE calendarsubscriptions (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
uri VARBINARY(200) NOT NULL,
|
||||
principaluri VARBINARY(100) NOT NULL,
|
||||
source TEXT,
|
||||
displayname VARCHAR(100),
|
||||
refreshrate VARCHAR(10),
|
||||
calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
|
||||
calendarcolor VARBINARY(10),
|
||||
striptodos TINYINT(1) NULL,
|
||||
stripalarms TINYINT(1) NULL,
|
||||
stripattachments TINYINT(1) NULL,
|
||||
lastmodified INT(11) UNSIGNED,
|
||||
UNIQUE(principaluri, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE schedulingobjects (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARBINARY(255),
|
||||
calendardata MEDIUMBLOB,
|
||||
uri VARBINARY(200),
|
||||
lastmodified INT(11) UNSIGNED,
|
||||
etag VARBINARY(32),
|
||||
size INT(11) UNSIGNED NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
12
vendor/sabre/dav/examples/sql/mysql.locks.sql
vendored
12
vendor/sabre/dav/examples/sql/mysql.locks.sql
vendored
@ -1,12 +0,0 @@
|
||||
CREATE TABLE locks (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
owner VARCHAR(100),
|
||||
timeout INTEGER UNSIGNED,
|
||||
created INTEGER,
|
||||
token VARBINARY(100),
|
||||
scope TINYINT,
|
||||
depth TINYINT,
|
||||
uri VARBINARY(1000),
|
||||
INDEX(token),
|
||||
INDEX(uri(100))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
@ -1,20 +0,0 @@
|
||||
CREATE TABLE principals (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
uri VARBINARY(200) NOT NULL,
|
||||
email VARBINARY(80),
|
||||
displayname VARCHAR(80),
|
||||
UNIQUE(uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principal_id INTEGER UNSIGNED NOT NULL,
|
||||
member_id INTEGER UNSIGNED NOT NULL,
|
||||
UNIQUE(principal_id, member_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO principals (uri,email,displayname) VALUES
|
||||
('principals/admin', 'admin@example.org','Administrator'),
|
||||
('principals/admin/calendar-proxy-read', null, null),
|
||||
('principals/admin/calendar-proxy-write', null, null);
|
||||
|
@ -1,9 +0,0 @@
|
||||
CREATE TABLE users (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
username VARBINARY(50),
|
||||
digesta1 VARBINARY(32),
|
||||
UNIQUE(username)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO users (username,digesta1) VALUES
|
||||
('admin', '87fd274b7b6c01e48d7c2f965da8ddf7');
|
@ -1,52 +0,0 @@
|
||||
CREATE TABLE addressbooks (
|
||||
id SERIAL NOT NULL,
|
||||
principaluri VARCHAR(255),
|
||||
displayname VARCHAR(255),
|
||||
uri VARCHAR(200),
|
||||
description TEXT,
|
||||
synctoken INTEGER NOT NULL DEFAULT 1
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY addressbooks
|
||||
ADD CONSTRAINT addressbooks_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX addressbooks_ukey
|
||||
ON addressbooks USING btree (principaluri, uri);
|
||||
|
||||
CREATE TABLE cards (
|
||||
id SERIAL NOT NULL,
|
||||
addressbookid INTEGER NOT NULL,
|
||||
carddata TEXT,
|
||||
uri VARCHAR(200),
|
||||
lastmodified INTEGER,
|
||||
etag VARCHAR(32),
|
||||
size INTEGER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY cards
|
||||
ADD CONSTRAINT cards_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX cards_ukey
|
||||
ON cards USING btree (addressbookid, uri);
|
||||
|
||||
ALTER TABLE ONLY cards
|
||||
ADD CONSTRAINT cards_addressbookid_fkey FOREIGN KEY (addressbookid) REFERENCES addressbooks(id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
CREATE TABLE addressbookchanges (
|
||||
id SERIAL NOT NULL,
|
||||
uri VARCHAR(200) NOT NULL,
|
||||
synctoken INTEGER NOT NULL,
|
||||
addressbookid INTEGER NOT NULL,
|
||||
operation SMALLINT NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY addressbookchanges
|
||||
ADD CONSTRAINT addressbookchanges_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE INDEX addressbookchanges_addressbookid_synctoken_ix
|
||||
ON addressbookchanges USING btree (addressbookid, synctoken);
|
||||
|
||||
ALTER TABLE ONLY addressbookchanges
|
||||
ADD CONSTRAINT addressbookchanges_addressbookid_fkey FOREIGN KEY (addressbookid) REFERENCES addressbooks(id)
|
||||
ON DELETE CASCADE;
|
@ -1,93 +0,0 @@
|
||||
CREATE TABLE calendars (
|
||||
id SERIAL NOT NULL,
|
||||
principaluri VARCHAR(100),
|
||||
displayname VARCHAR(100),
|
||||
uri VARCHAR(200),
|
||||
synctoken INTEGER NOT NULL DEFAULT 1,
|
||||
description TEXT,
|
||||
calendarorder INTEGER NOT NULL DEFAULT 0,
|
||||
calendarcolor VARCHAR(10),
|
||||
timezone TEXT,
|
||||
components VARCHAR(20),
|
||||
uid VARCHAR(200),
|
||||
transparent SMALLINT NOT NULL DEFAULT '0'
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendars
|
||||
ADD CONSTRAINT calendars_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX calendars_ukey
|
||||
ON calendars USING btree (principaluri, uri);
|
||||
|
||||
CREATE TABLE calendarobjects (
|
||||
id SERIAL NOT NULL,
|
||||
calendardata TEXT,
|
||||
uri VARCHAR(200),
|
||||
calendarid INTEGER NOT NULL,
|
||||
lastmodified INTEGER,
|
||||
etag VARCHAR(32),
|
||||
size INTEGER NOT NULL,
|
||||
componenttype VARCHAR(8),
|
||||
firstoccurence INTEGER,
|
||||
lastoccurence INTEGER,
|
||||
uid VARCHAR(200)
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendarobjects
|
||||
ADD CONSTRAINT calendarobjects_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX calendarobjects_ukey
|
||||
ON calendarobjects USING btree (calendarid, uri);
|
||||
|
||||
ALTER TABLE ONLY calendarobjects
|
||||
ADD CONSTRAINT calendarobjects_calendarid_fkey FOREIGN KEY (calendarid) REFERENCES calendars(id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
CREATE TABLE calendarsubscriptions (
|
||||
id SERIAL NOT NULL,
|
||||
uri VARCHAR(200) NOT NULL,
|
||||
principaluri VARCHAR(100) NOT NULL,
|
||||
source TEXT,
|
||||
displayname VARCHAR(100),
|
||||
refreshrate VARCHAR(10),
|
||||
calendarorder INTEGER NOT NULL DEFAULT 0,
|
||||
calendarcolor VARCHAR(10),
|
||||
striptodos SMALLINT NULL,
|
||||
stripalarms SMALLINT NULL,
|
||||
stripattachments SMALLINT NULL,
|
||||
lastmodified INTEGER
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendarsubscriptions
|
||||
ADD CONSTRAINT calendarsubscriptions_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX calendarsubscriptions_ukey
|
||||
ON calendarsubscriptions USING btree (principaluri, uri);
|
||||
|
||||
CREATE TABLE calendarchanges (
|
||||
id SERIAL NOT NULL,
|
||||
uri VARCHAR(200) NOT NULL,
|
||||
synctoken INTEGER NOT NULL,
|
||||
calendarid INTEGER NOT NULL,
|
||||
operation SMALLINT NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendarchanges
|
||||
ADD CONSTRAINT calendarchanges_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE INDEX calendarchanges_calendarid_synctoken_ix
|
||||
ON calendarchanges USING btree (calendarid, synctoken);
|
||||
|
||||
ALTER TABLE ONLY calendarchanges
|
||||
ADD CONSTRAINT calendarchanges_calendar_fk FOREIGN KEY (calendarid) REFERENCES calendars(id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
CREATE TABLE schedulingobjects (
|
||||
id SERIAL NOT NULL,
|
||||
principaluri VARCHAR(255),
|
||||
calendardata BYTEA,
|
||||
uri VARCHAR(200),
|
||||
lastmodified INTEGER,
|
||||
etag VARCHAR(32),
|
||||
size INTEGER NOT NULL
|
||||
);
|
19
vendor/sabre/dav/examples/sql/pgsql.locks.sql
vendored
19
vendor/sabre/dav/examples/sql/pgsql.locks.sql
vendored
@ -1,19 +0,0 @@
|
||||
CREATE TABLE locks (
|
||||
id SERIAL NOT NULL,
|
||||
owner VARCHAR(100),
|
||||
timeout INTEGER,
|
||||
created INTEGER,
|
||||
token VARCHAR(100),
|
||||
scope SMALLINT,
|
||||
depth SMALLINT,
|
||||
uri TEXT
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY locks
|
||||
ADD CONSTRAINT locks_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE INDEX locks_token_ix
|
||||
ON locks USING btree (token);
|
||||
|
||||
CREATE INDEX locks_uri_ix
|
||||
ON locks USING btree (uri);
|
@ -1,38 +0,0 @@
|
||||
CREATE TABLE principals (
|
||||
id SERIAL NOT NULL,
|
||||
uri VARCHAR(200) NOT NULL,
|
||||
email VARCHAR(80),
|
||||
displayname VARCHAR(80)
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY principals
|
||||
ADD CONSTRAINT principals_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX principals_ukey
|
||||
ON principals USING btree (uri);
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id SERIAL NOT NULL,
|
||||
principal_id INTEGER NOT NULL,
|
||||
member_id INTEGER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY groupmembers
|
||||
ADD CONSTRAINT groupmembers_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX groupmembers_ukey
|
||||
ON groupmembers USING btree (principal_id, member_id);
|
||||
|
||||
ALTER TABLE ONLY groupmembers
|
||||
ADD CONSTRAINT groupmembers_principal_id_fkey FOREIGN KEY (principal_id) REFERENCES principals(id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY groupmembers
|
||||
ADD CONSTRAINT groupmembers_member_id_id_fkey FOREIGN KEY (member_id) REFERENCES principals(id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO principals (uri,email,displayname) VALUES
|
||||
('principals/admin', 'admin@example.org','Administrator'),
|
||||
('principals/admin/calendar-proxy-read', null, null),
|
||||
('principals/admin/calendar-proxy-write', null, null);
|
||||
|
14
vendor/sabre/dav/examples/sql/pgsql.users.sql
vendored
14
vendor/sabre/dav/examples/sql/pgsql.users.sql
vendored
@ -1,14 +0,0 @@
|
||||
CREATE TABLE users (
|
||||
id SERIAL NOT NULL,
|
||||
username VARCHAR(50),
|
||||
digesta1 VARCHAR(32)
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY users
|
||||
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX users_ukey
|
||||
ON users USING btree (username);
|
||||
|
||||
INSERT INTO users (username,digesta1) VALUES
|
||||
('admin', '87fd274b7b6c01e48d7c2f965da8ddf7');
|
@ -1,28 +0,0 @@
|
||||
CREATE TABLE addressbooks (
|
||||
id integer primary key asc NOT NULL,
|
||||
principaluri text NOT NULL,
|
||||
displayname text,
|
||||
uri text NOT NULL,
|
||||
description text,
|
||||
synctoken integer DEFAULT 1 NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE cards (
|
||||
id integer primary key asc NOT NULL,
|
||||
addressbookid integer NOT NULL,
|
||||
carddata blob,
|
||||
uri text NOT NULL,
|
||||
lastmodified integer,
|
||||
etag text,
|
||||
size integer
|
||||
);
|
||||
|
||||
CREATE TABLE addressbookchanges (
|
||||
id integer primary key asc NOT NULL,
|
||||
uri text,
|
||||
synctoken integer NOT NULL,
|
||||
addressbookid integer NOT NULL,
|
||||
operation integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX addressbookid_synctoken ON addressbookchanges (addressbookid, synctoken);
|
@ -1,64 +0,0 @@
|
||||
CREATE TABLE calendarobjects (
|
||||
id integer primary key asc NOT NULL,
|
||||
calendardata blob NOT NULL,
|
||||
uri text NOT NULL,
|
||||
calendarid integer NOT NULL,
|
||||
lastmodified integer NOT NULL,
|
||||
etag text NOT NULL,
|
||||
size integer NOT NULL,
|
||||
componenttype text,
|
||||
firstoccurence integer,
|
||||
lastoccurence integer,
|
||||
uid text
|
||||
);
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id integer primary key asc NOT NULL,
|
||||
principaluri text NOT NULL,
|
||||
displayname text,
|
||||
uri text NOT NULL,
|
||||
synctoken integer DEFAULT 1 NOT NULL,
|
||||
description text,
|
||||
calendarorder integer,
|
||||
calendarcolor text,
|
||||
timezone text,
|
||||
components text NOT NULL,
|
||||
transparent bool
|
||||
);
|
||||
|
||||
CREATE TABLE calendarchanges (
|
||||
id integer primary key asc NOT NULL,
|
||||
uri text,
|
||||
synctoken integer NOT NULL,
|
||||
calendarid integer NOT NULL,
|
||||
operation integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX calendarid_synctoken ON calendarchanges (calendarid, synctoken);
|
||||
|
||||
CREATE TABLE calendarsubscriptions (
|
||||
id integer primary key asc NOT NULL,
|
||||
uri text NOT NULL,
|
||||
principaluri text NOT NULL,
|
||||
source text NOT NULL,
|
||||
displayname text,
|
||||
refreshrate text,
|
||||
calendarorder integer,
|
||||
calendarcolor text,
|
||||
striptodos bool,
|
||||
stripalarms bool,
|
||||
stripattachments bool,
|
||||
lastmodified int
|
||||
);
|
||||
|
||||
CREATE TABLE schedulingobjects (
|
||||
id integer primary key asc NOT NULL,
|
||||
principaluri text NOT NULL,
|
||||
calendardata blob,
|
||||
uri text NOT NULL,
|
||||
lastmodified integer,
|
||||
etag text NOT NULL,
|
||||
size integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri);
|
12
vendor/sabre/dav/examples/sql/sqlite.locks.sql
vendored
12
vendor/sabre/dav/examples/sql/sqlite.locks.sql
vendored
@ -1,12 +0,0 @@
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE locks (
|
||||
id integer primary key asc NOT NULL,
|
||||
owner text,
|
||||
timeout integer,
|
||||
created integer,
|
||||
token text,
|
||||
scope integer,
|
||||
depth integer,
|
||||
uri text
|
||||
);
|
||||
COMMIT;
|
@ -1,20 +0,0 @@
|
||||
CREATE TABLE principals (
|
||||
id INTEGER PRIMARY KEY ASC NOT NULL,
|
||||
uri TEXT NOT NULL,
|
||||
email TEXT,
|
||||
displayname TEXT,
|
||||
UNIQUE(uri)
|
||||
);
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id INTEGER PRIMARY KEY ASC NOT NULL,
|
||||
principal_id INTEGER NOT NULL,
|
||||
member_id INTEGER NOT NULL,
|
||||
UNIQUE(principal_id, member_id)
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin', 'admin@example.org','Administrator');
|
||||
INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-read', null, null);
|
||||
INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-write', null, null);
|
||||
|
@ -1,9 +0,0 @@
|
||||
CREATE TABLE users (
|
||||
id integer primary key asc NOT NULL,
|
||||
username TEXT NOT NULL,
|
||||
digesta1 TEXT NOT NULL,
|
||||
UNIQUE(username)
|
||||
);
|
||||
|
||||
INSERT INTO users (username,digesta1) VALUES
|
||||
('admin', '87fd274b7b6c01e48d7c2f965da8ddf7');
|
@ -1,16 +0,0 @@
|
||||
RewriteEngine On
|
||||
# This makes every request go to server.php
|
||||
RewriteRule (.*) server.php [L]
|
||||
|
||||
# Output buffering needs to be off, to prevent high memory usage
|
||||
php_flag output_buffering off
|
||||
|
||||
# This is also to prevent high memory usage
|
||||
php_flag always_populate_raw_post_data off
|
||||
|
||||
# This is almost a given, but magic quotes is *still* on on some
|
||||
# linux distributions
|
||||
php_flag magic_quotes_gpc off
|
||||
|
||||
# SabreDAV is not compatible with mbstring function overloading
|
||||
php_flag mbstring.func_overload off
|
@ -1,29 +0,0 @@
|
||||
# This is a sample configuration to setup a dedicated Apache vhost for WebDAV.
|
||||
#
|
||||
# The main thing that should be configured is the servername, and the path to
|
||||
# your SabreDAV installation (DocumentRoot).
|
||||
#
|
||||
# This configuration assumed mod_php5 is used, as it sets a few default php
|
||||
# settings as well.
|
||||
<VirtualHost *:*>
|
||||
|
||||
# Don't forget to change the server name
|
||||
# ServerName dav.example.org
|
||||
|
||||
# The DocumentRoot is also required
|
||||
# DocumentRoot /home/sabredav/
|
||||
|
||||
RewriteEngine On
|
||||
# This makes every request go to server.php
|
||||
RewriteRule ^/(.*)$ /server.php [L]
|
||||
|
||||
# Output buffering needs to be off, to prevent high memory usage
|
||||
php_flag output_buffering off
|
||||
|
||||
# This is also to prevent high memory usage
|
||||
php_flag always_populate_raw_post_data off
|
||||
|
||||
# SabreDAV is not compatible with mbstring function overloading
|
||||
php_flag mbstring.func_overload off
|
||||
|
||||
</VirtualHost *:*>
|
@ -1,21 +0,0 @@
|
||||
# This is a sample configuration to setup a dedicated Apache vhost for WebDAV.
|
||||
#
|
||||
# The main thing that should be configured is the servername, and the path to
|
||||
# your SabreDAV installation (DocumentRoot).
|
||||
#
|
||||
# This configuration assumes CGI or FastCGI is used.
|
||||
<VirtualHost *:*>
|
||||
|
||||
# Don't forget to change the server name
|
||||
# ServerName dav.example.org
|
||||
|
||||
# The DocumentRoot is also required
|
||||
# DocumentRoot /home/sabredav/
|
||||
|
||||
# This makes every request go to server.php. This also makes sure
|
||||
# the Authentication information is available. If your server script is
|
||||
# not called server.php, be sure to change it.
|
||||
RewriteEngine On
|
||||
RewriteRule ^/(.*)$ /server.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
</VirtualHost *:*>
|
@ -44,10 +44,12 @@ interface BackendInterface {
|
||||
* If the creation was a success, an id must be returned that can be used to
|
||||
* reference this calendar in other methods, such as updateCalendar.
|
||||
*
|
||||
* The id can be any type, including ints, strings, objects or array.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @param string $calendarUri
|
||||
* @param array $properties
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
function createCalendar($principalUri, $calendarUri, array $properties);
|
||||
|
||||
@ -63,7 +65,7 @@ interface BackendInterface {
|
||||
*
|
||||
* Read the PropPatch documentation for more info and examples.
|
||||
*
|
||||
* @param string $path
|
||||
* @param mixed $calendarId
|
||||
* @param \Sabre\DAV\PropPatch $propPatch
|
||||
* @return void
|
||||
*/
|
||||
|
@ -43,4 +43,19 @@ interface NotificationSupport extends BackendInterface {
|
||||
*/
|
||||
function deleteNotification($principalUri, NotificationInterface $notification);
|
||||
|
||||
/**
|
||||
* This method is called when a user replied to a request to share.
|
||||
*
|
||||
* If the user chose to accept the share, this method should return the
|
||||
* newly created calendar url.
|
||||
*
|
||||
* @param string href The sharee who is replying (often a mailto: address)
|
||||
* @param int status One of the SharingPlugin::STATUS_* constants
|
||||
* @param string $calendarUri The url to the calendar thats being shared
|
||||
* @param string $inReplyTo The unique id this message is a response to
|
||||
* @param string $summary A description of the reply
|
||||
* @return null|string
|
||||
*/
|
||||
function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null);
|
||||
|
||||
}
|
||||
|
381
vendor/sabre/dav/lib/CalDAV/Backend/PDO.php
vendored
381
vendor/sabre/dav/lib/CalDAV/Backend/PDO.php
vendored
@ -2,10 +2,11 @@
|
||||
|
||||
namespace Sabre\CalDAV\Backend;
|
||||
|
||||
use Sabre\VObject;
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAV\Exception\Forbidden;
|
||||
use Sabre\VObject;
|
||||
use Sabre\DAV\Xml\Element\Sharee;
|
||||
|
||||
/**
|
||||
* PDO CalDAV backend
|
||||
@ -17,7 +18,12 @@ use Sabre\DAV\Exception\Forbidden;
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport {
|
||||
class PDO extends AbstractBackend
|
||||
implements
|
||||
SyncSupport,
|
||||
SubscriptionSupport,
|
||||
SchedulingSupport,
|
||||
SharingSupport {
|
||||
|
||||
/**
|
||||
* We need to specify a max date, because we need to stop *somewhere*
|
||||
@ -43,6 +49,16 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*/
|
||||
public $calendarTableName = 'calendars';
|
||||
|
||||
/**
|
||||
* The table name that will be used for calendars instances.
|
||||
*
|
||||
* A single calendar can have multiple instances, if the calendar is
|
||||
* shared.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $calendarInstancesTableName = 'calendarinstances';
|
||||
|
||||
/**
|
||||
* The table name that will be used for calendar objects
|
||||
*
|
||||
@ -140,16 +156,23 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
function getCalendarsForUser($principalUri) {
|
||||
|
||||
$fields = array_values($this->propertyMap);
|
||||
$fields[] = 'id';
|
||||
$fields[] = 'calendarid';
|
||||
$fields[] = 'uri';
|
||||
$fields[] = 'synctoken';
|
||||
$fields[] = 'components';
|
||||
$fields[] = 'principaluri';
|
||||
$fields[] = 'transparent';
|
||||
$fields[] = 'access';
|
||||
|
||||
// Making fields a comma-delimited list
|
||||
$fields = implode(', ', $fields);
|
||||
$stmt = $this->pdo->prepare("SELECT " . $fields . " FROM " . $this->calendarTableName . " WHERE principaluri = ? ORDER BY calendarorder ASC");
|
||||
$stmt = $this->pdo->prepare(<<<SQL
|
||||
SELECT {$this->calendarInstancesTableName}.id as id, $fields FROM {$this->calendarInstancesTableName}
|
||||
LEFT JOIN {$this->calendarTableName} ON
|
||||
{$this->calendarInstancesTableName}.calendarid = {$this->calendarTableName}.id
|
||||
WHERE principaluri = ? ORDER BY calendarorder ASC
|
||||
SQL
|
||||
);
|
||||
$stmt->execute([$principalUri]);
|
||||
|
||||
$calendars = [];
|
||||
@ -161,15 +184,27 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
}
|
||||
|
||||
$calendar = [
|
||||
'id' => $row['id'],
|
||||
'id' => [(int)$row['calendarid'], (int)$row['id']],
|
||||
'uri' => $row['uri'],
|
||||
'principaluri' => $row['principaluri'],
|
||||
'{' . CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => 'http://sabre.io/ns/sync/' . ($row['synctoken'] ? $row['synctoken'] : '0'),
|
||||
'{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0',
|
||||
'{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Xml\Property\SupportedCalendarComponentSet($components),
|
||||
'{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' => new CalDAV\Xml\Property\ScheduleCalendarTransp($row['transparent'] ? 'transparent' : 'opaque'),
|
||||
'share-resource-uri' => '/ns/share/' . $row['calendarid'],
|
||||
];
|
||||
|
||||
$calendar['share-access'] = (int)$row['access'];
|
||||
// 1 = owner, 2 = readonly, 3 = readwrite
|
||||
if ($row['access'] > 1) {
|
||||
// We need to find more information about the original owner.
|
||||
//$stmt2 = $this->pdo->prepare('SELECT principaluri FROM ' . $this->calendarInstancesTableName . ' WHERE access = 1 AND id = ?');
|
||||
//$stmt2->execute([$row['id']]);
|
||||
|
||||
// read-only is for backwards compatbility. Might go away in
|
||||
// the future.
|
||||
$calendar['read-only'] = (int)$row['access'] === \Sabre\DAV\Sharing\Plugin::ACCESS_READ;
|
||||
}
|
||||
|
||||
foreach ($this->propertyMap as $xmlName => $dbName) {
|
||||
$calendar[$xmlName] = $row[$dbName];
|
||||
@ -199,31 +234,38 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
$fieldNames = [
|
||||
'principaluri',
|
||||
'uri',
|
||||
'synctoken',
|
||||
'transparent',
|
||||
'calendarid',
|
||||
];
|
||||
$values = [
|
||||
':principaluri' => $principalUri,
|
||||
':uri' => $calendarUri,
|
||||
':synctoken' => 1,
|
||||
':transparent' => 0,
|
||||
];
|
||||
|
||||
// Default value
|
||||
|
||||
$sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
|
||||
$fieldNames[] = 'components';
|
||||
if (!isset($properties[$sccs])) {
|
||||
$values[':components'] = 'VEVENT,VTODO';
|
||||
// Default value
|
||||
$components = 'VEVENT,VTODO';
|
||||
} else {
|
||||
if (!($properties[$sccs] instanceof CalDAV\Xml\Property\SupportedCalendarComponentSet)) {
|
||||
throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet');
|
||||
}
|
||||
$values[':components'] = implode(',', $properties[$sccs]->getValue());
|
||||
$components = implode(',', $properties[$sccs]->getValue());
|
||||
}
|
||||
$transp = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp';
|
||||
if (isset($properties[$transp])) {
|
||||
$values[':transparent'] = $properties[$transp]->getValue() === 'transparent';
|
||||
$values[':transparent'] = $properties[$transp]->getValue() === 'transparent' ? 1 : 0;
|
||||
}
|
||||
$stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (synctoken, components) VALUES (1, ?)");
|
||||
$stmt->execute([$components]);
|
||||
|
||||
$calendarId = $this->pdo->lastInsertId(
|
||||
$this->calendarTableName . '_id_seq'
|
||||
);
|
||||
|
||||
$values[':calendarid'] = $calendarId;
|
||||
|
||||
foreach ($this->propertyMap as $xmlName => $dbName) {
|
||||
if (isset($properties[$xmlName])) {
|
||||
@ -233,10 +275,14 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
|
||||
$stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarInstancesTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
|
||||
|
||||
$stmt->execute($values);
|
||||
|
||||
return $this->pdo->lastInsertId();
|
||||
return [
|
||||
$calendarId,
|
||||
$this->pdo->lastInsertId($this->calendarInstancesTableName . '_id_seq')
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
@ -252,16 +298,21 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*
|
||||
* Read the PropPatch documenation for more info and examples.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @param \Sabre\DAV\PropPatch $propPatch
|
||||
* @return void
|
||||
*/
|
||||
function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$supportedProperties = array_keys($this->propertyMap);
|
||||
$supportedProperties[] = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp';
|
||||
|
||||
$propPatch->handle($supportedProperties, function($mutations) use ($calendarId) {
|
||||
$propPatch->handle($supportedProperties, function($mutations) use ($calendarId, $instanceId) {
|
||||
$newValues = [];
|
||||
foreach ($mutations as $propertyName => $propertyValue) {
|
||||
|
||||
@ -282,8 +333,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
$valuesSql[] = $fieldName . ' = ?';
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?");
|
||||
$newValues['id'] = $calendarId;
|
||||
$stmt = $this->pdo->prepare("UPDATE " . $this->calendarInstancesTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?");
|
||||
$newValues['id'] = $instanceId;
|
||||
$stmt->execute(array_values($newValues));
|
||||
|
||||
$this->addChange($calendarId, "", 2);
|
||||
@ -297,19 +348,49 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
/**
|
||||
* Delete a calendar and all it's objects
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @return void
|
||||
*/
|
||||
function deleteCalendar($calendarId) {
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarTableName . ' WHERE id = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
$stmt = $this->pdo->prepare('SELECT access FROM ' . $this->calendarInstancesTableName . ' where id = ?');
|
||||
$stmt->execute([$instanceId]);
|
||||
$access = (int)$stmt->fetchColumn();
|
||||
|
||||
if ($access === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER) {
|
||||
|
||||
/**
|
||||
* If the user is the owner of the calendar, we delete all data and all
|
||||
* instances.
|
||||
**/
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarChangesTableName . ' WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarInstancesTableName . ' WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarTableName . ' WHERE id = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
} else {
|
||||
|
||||
/**
|
||||
* If it was an instance of a shared calendar, we only delete that
|
||||
* instance.
|
||||
*/
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarInstancesTableName . ' WHERE id = ?');
|
||||
$stmt->execute([$instanceId]);
|
||||
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarChangesTableName . ' WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
}
|
||||
|
||||
@ -341,11 +422,16 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
* used/fetched to determine these numbers. If both are specified the
|
||||
* amount of times this is needed is reduced by a great degree.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @return array
|
||||
*/
|
||||
function getCalendarObjects($calendarId) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
@ -354,9 +440,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
$result[] = [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'lastmodified' => $row['lastmodified'],
|
||||
'lastmodified' => (int)$row['lastmodified'],
|
||||
'etag' => '"' . $row['etag'] . '"',
|
||||
'calendarid' => $row['calendarid'],
|
||||
'size' => (int)$row['size'],
|
||||
'component' => strtolower($row['componenttype']),
|
||||
];
|
||||
@ -378,12 +463,17 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*
|
||||
* This method must return null if the object did not exist.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @param string $objectUri
|
||||
* @return array|null
|
||||
*/
|
||||
function getCalendarObject($calendarId, $objectUri) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, calendardata, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute([$calendarId, $objectUri]);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
@ -393,9 +483,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
return [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'lastmodified' => $row['lastmodified'],
|
||||
'lastmodified' => (int)$row['lastmodified'],
|
||||
'etag' => '"' . $row['etag'] . '"',
|
||||
'calendarid' => $row['calendarid'],
|
||||
'size' => (int)$row['size'],
|
||||
'calendardata' => $row['calendardata'],
|
||||
'component' => strtolower($row['componenttype']),
|
||||
@ -417,6 +506,11 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*/
|
||||
function getMultipleCalendarObjects($calendarId, array $uris) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$query = 'SELECT id, uri, lastmodified, etag, calendarid, size, calendardata, componenttype FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri IN (';
|
||||
// Inserting a whole bunch of question marks
|
||||
$query .= implode(',', array_fill(0, count($uris), '?'));
|
||||
@ -431,9 +525,8 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
$result[] = [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'lastmodified' => $row['lastmodified'],
|
||||
'lastmodified' => (int)$row['lastmodified'],
|
||||
'etag' => '"' . $row['etag'] . '"',
|
||||
'calendarid' => $row['calendarid'],
|
||||
'size' => (int)$row['size'],
|
||||
'calendardata' => $row['calendardata'],
|
||||
'component' => strtolower($row['componenttype']),
|
||||
@ -465,6 +558,11 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*/
|
||||
function createCalendarObject($calendarId, $objectUri, $calendarData) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$extraData = $this->getDenormalizedData($calendarData);
|
||||
|
||||
$stmt = $this->pdo->prepare('INSERT INTO ' . $this->calendarObjectTableName . ' (calendarid, uri, calendardata, lastmodified, etag, size, componenttype, firstoccurence, lastoccurence, uid) VALUES (?,?,?,?,?,?,?,?,?,?)');
|
||||
@ -506,6 +604,11 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*/
|
||||
function updateCalendarObject($calendarId, $objectUri, $calendarData) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$extraData = $this->getDenormalizedData($calendarData);
|
||||
|
||||
$stmt = $this->pdo->prepare('UPDATE ' . $this->calendarObjectTableName . ' SET calendardata = ?, lastmodified = ?, etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ?, uid = ? WHERE calendarid = ? AND uri = ?');
|
||||
@ -583,6 +686,10 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensure Occurence values are positive
|
||||
if ($firstOccurence < 0) $firstOccurence = 0;
|
||||
if ($lastOccurence < 0) $lastOccurence = 0;
|
||||
}
|
||||
|
||||
// Destroy circular references to PHP will GC the object.
|
||||
@ -604,12 +711,17 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
*
|
||||
* The object uri is only the basename, or filename and not a full path.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @param string $objectUri
|
||||
* @return void
|
||||
*/
|
||||
function deleteCalendarObject($calendarId, $objectUri) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->calendarObjectTableName . ' WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute([$calendarId, $objectUri]);
|
||||
|
||||
@ -665,12 +777,17 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
* This specific implementation (for the PDO) backend optimizes filters on
|
||||
* specific components, and VEVENT time-ranges.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @param array $filters
|
||||
* @return array
|
||||
*/
|
||||
function calendarQuery($calendarId, array $filters) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$componentType = null;
|
||||
$requirePostFilter = true;
|
||||
$timeRange = null;
|
||||
@ -766,14 +883,14 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
|
||||
|
||||
$query = <<<SQL
|
||||
SELECT
|
||||
calendars.uri AS calendaruri, calendarobjects.uri as objecturi
|
||||
calendar_instances.uri AS calendaruri, calendarobjects.uri as objecturi
|
||||
FROM
|
||||
$this->calendarObjectTableName AS calendarobjects
|
||||
LEFT JOIN
|
||||
$this->calendarTableName AS calendars
|
||||
ON calendarobjects.calendarid = calendars.id
|
||||
$this->calendarInstancesTableName AS calendar_instances
|
||||
ON calendarobjects.calendarid = calendar_instances.calendarid
|
||||
WHERE
|
||||
calendars.principaluri = ?
|
||||
calendar_instances.principaluri = ?
|
||||
AND
|
||||
calendarobjects.uid = ?
|
||||
SQL;
|
||||
@ -837,7 +954,7 @@ SQL;
|
||||
*
|
||||
* The limit is 'suggestive'. You are free to ignore it.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param mixed $calendarId
|
||||
* @param string $syncToken
|
||||
* @param int $syncLevel
|
||||
* @param int $limit
|
||||
@ -845,6 +962,11 @@ SQL;
|
||||
*/
|
||||
function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
// Current synctoken
|
||||
$stmt = $this->pdo->prepare('SELECT synctoken FROM ' . $this->calendarTableName . ' WHERE id = ?');
|
||||
$stmt->execute([ $calendarId ]);
|
||||
@ -1043,7 +1165,9 @@ SQL;
|
||||
$stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarSubscriptionsTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
|
||||
$stmt->execute($values);
|
||||
|
||||
return $this->pdo->lastInsertId();
|
||||
return $this->pdo->lastInsertId(
|
||||
$this->calendarSubscriptionsTableName . '_id_seq'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -1207,4 +1331,179 @@ SQL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of shares.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
|
||||
* @return void
|
||||
*/
|
||||
function updateInvites($calendarId, array $sharees) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to $calendarId is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
$currentInvites = $this->getInvites($calendarId);
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$removeStmt = $this->pdo->prepare("DELETE FROM " . $this->calendarInstancesTableName . " WHERE calendarid = ? AND share_href = ? AND access IN (2,3)");
|
||||
$updateStmt = $this->pdo->prepare("UPDATE " . $this->calendarInstancesTableName . " SET access = ?, share_displayname = ?, share_invitestatus = ? WHERE calendarid = ? AND share_href = ?");
|
||||
|
||||
$insertStmt = $this->pdo->prepare('
|
||||
INSERT INTO ' . $this->calendarInstancesTableName . '
|
||||
(
|
||||
calendarid,
|
||||
principaluri,
|
||||
access,
|
||||
displayname,
|
||||
uri,
|
||||
description,
|
||||
calendarorder,
|
||||
calendarcolor,
|
||||
timezone,
|
||||
transparent,
|
||||
share_href,
|
||||
share_displayname,
|
||||
share_invitestatus
|
||||
)
|
||||
SELECT
|
||||
?,
|
||||
?,
|
||||
?,
|
||||
displayname,
|
||||
?,
|
||||
description,
|
||||
calendarorder,
|
||||
calendarcolor,
|
||||
timezone,
|
||||
1,
|
||||
?,
|
||||
?,
|
||||
?
|
||||
FROM ' . $this->calendarInstancesTableName . ' WHERE id = ?');
|
||||
|
||||
foreach ($sharees as $sharee) {
|
||||
|
||||
if ($sharee->access === \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS) {
|
||||
// if access was set no NOACCESS, it means access for an
|
||||
// existing sharee was removed.
|
||||
$removeStmt->execute([$calendarId, $sharee->href]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_null($sharee->principal)) {
|
||||
// If the server could not determine the principal automatically,
|
||||
// we will mark the invite status as invalid.
|
||||
$sharee->inviteStatus = \Sabre\DAV\Sharing\Plugin::INVITE_INVALID;
|
||||
} else {
|
||||
// Because sabre/dav does not yet have an invitation system,
|
||||
// every invite is automatically accepted for now.
|
||||
$sharee->inviteStatus = \Sabre\DAV\Sharing\Plugin::INVITE_ACCEPTED;
|
||||
}
|
||||
|
||||
foreach ($currentInvites as $oldSharee) {
|
||||
|
||||
if ($oldSharee->href === $sharee->href) {
|
||||
// This is an update
|
||||
$sharee->properties = array_merge(
|
||||
$oldSharee->properties,
|
||||
$sharee->properties
|
||||
);
|
||||
$updateStmt->execute([
|
||||
$sharee->access,
|
||||
isset($sharee->properties['{DAV:}displayname']) ? $sharee->properties['{DAV:}displayname'] : null,
|
||||
$sharee->inviteStatus ?: $oldSharee->inviteStatus,
|
||||
$calendarId,
|
||||
$sharee->href
|
||||
]);
|
||||
continue 2;
|
||||
}
|
||||
|
||||
}
|
||||
// If we got here, it means it was a new sharee
|
||||
$insertStmt->execute([
|
||||
$calendarId,
|
||||
$sharee->principal,
|
||||
$sharee->access,
|
||||
\Sabre\DAV\UUIDUtil::getUUID(),
|
||||
$sharee->href,
|
||||
isset($sharee->properties['{DAV:}displayname']) ? $sharee->properties['{DAV:}displayname'] : null,
|
||||
$sharee->inviteStatus ?: \Sabre\DAV\Sharing\Plugin::INVITE_NORESPONSE,
|
||||
$instanceId
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of people whom a calendar is shared with.
|
||||
*
|
||||
* Every item in the returned list must be a Sharee object with at
|
||||
* least the following properties set:
|
||||
* $href
|
||||
* $shareAccess
|
||||
* $inviteStatus
|
||||
*
|
||||
* and optionally:
|
||||
* $properties
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @return \Sabre\DAV\Xml\Element\Sharee[]
|
||||
*/
|
||||
function getInvites($calendarId) {
|
||||
|
||||
if (!is_array($calendarId)) {
|
||||
throw new \InvalidArgumentException('The value passed to getInvites() is expected to be an array with a calendarId and an instanceId');
|
||||
}
|
||||
list($calendarId, $instanceId) = $calendarId;
|
||||
|
||||
$query = <<<SQL
|
||||
SELECT
|
||||
principaluri,
|
||||
access,
|
||||
share_href,
|
||||
share_displayname,
|
||||
share_invitestatus
|
||||
FROM {$this->calendarInstancesTableName}
|
||||
WHERE
|
||||
calendarid = ?
|
||||
SQL;
|
||||
|
||||
$stmt = $this->pdo->prepare($query);
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
$result = [];
|
||||
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
|
||||
$result[] = new Sharee([
|
||||
'href' => isset($row['share_href']) ? $row['share_href'] : \Sabre\HTTP\encodePath($row['principaluri']),
|
||||
'access' => (int)$row['access'],
|
||||
/// Everyone is always immediately accepted, for now.
|
||||
'inviteStatus' => (int)$row['share_invitestatus'],
|
||||
'properties' =>
|
||||
!empty($row['share_displayname'])
|
||||
? [ '{DAV:}displayname' => $row['share_displayname'] ]
|
||||
: [],
|
||||
'principal' => $row['principaluri'],
|
||||
]);
|
||||
|
||||
}
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes a calendar
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
function setPublishStatus($calendarId, $value) {
|
||||
|
||||
throw new \Sabre\DAV\Exception\NotImplemented('Not implemented');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,231 +5,48 @@ namespace Sabre\CalDAV\Backend;
|
||||
/**
|
||||
* Adds support for sharing features to a CalDAV server.
|
||||
*
|
||||
* Note: This feature is experimental, and may change in between different
|
||||
* SabreDAV versions.
|
||||
* CalDAV backends that implement this interface, must make the following
|
||||
* modifications to getCalendarsForUser:
|
||||
*
|
||||
* Early warning: Currently SabreDAV provides no implementation for this. This
|
||||
* is, because in it's current state there is no elegant way to do this.
|
||||
* The problem lies in the fact that a real CalDAV server with sharing support
|
||||
* would first need email support (with invite notifications), and really also
|
||||
* a browser-frontend that allows people to accept or reject these shares.
|
||||
*
|
||||
* In addition, the CalDAV backends are currently kept as independent as
|
||||
* possible, and should not be aware of principals, email addresses or
|
||||
* accounts.
|
||||
*
|
||||
* Adding an implementation for Sharing to standard-sabredav would contradict
|
||||
* these goals, so for this reason this is currently not implemented, although
|
||||
* it may very well in the future; but probably not before SabreDAV 2.0.
|
||||
*
|
||||
* The interface works however, so if you implement all this, and do it
|
||||
* correctly sharing _will_ work. It's not particularly easy, and I _urge you_
|
||||
* to make yourself acquainted with the following document first:
|
||||
*
|
||||
* https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
|
||||
*
|
||||
* An overview
|
||||
* ===========
|
||||
*
|
||||
* Implementing this interface will allow a user to share his or her calendars
|
||||
* to other users. Effectively, when a calendar is shared the calendar will
|
||||
* show up in both the Sharer's and Sharee's calendar-home root.
|
||||
* This interface adds a few methods that ensure that this happens, and there
|
||||
* are also a number of new requirements in the base-class you must now follow.
|
||||
*
|
||||
*
|
||||
* How it works
|
||||
* ============
|
||||
*
|
||||
* When a user shares a calendar, the updateShares() method will be called with
|
||||
* a list of sharees that are now added, and a list of sharees that have been
|
||||
* removed.
|
||||
* Removal is instant, but when a sharee is added the sharee first gets a
|
||||
* chance to accept or reject the invitation for a share.
|
||||
*
|
||||
* After a share is accepted, the calendar will be returned from
|
||||
* getUserCalendars for both the sharer, and the sharee.
|
||||
*
|
||||
* If the sharee deletes the calendar, only their share gets deleted. When the
|
||||
* owner deletes a calendar, it will be removed for everybody.
|
||||
*
|
||||
*
|
||||
* Notifications
|
||||
* =============
|
||||
*
|
||||
* During all these sharing operations, a lot of notifications are sent back
|
||||
* and forward.
|
||||
*
|
||||
* Whenever the list of sharees for a calendar has been changed (they have been
|
||||
* added, removed or modified) all sharees should get a notification for this
|
||||
* change.
|
||||
* This notification is always represented by:
|
||||
*
|
||||
* Sabre\CalDAV\Notifications\Notification\Invite
|
||||
*
|
||||
* In the case of an invite, the sharee may reply with an 'accept' or
|
||||
* 'decline'. These are always represented by:
|
||||
*
|
||||
* Sabre\CalDAV\Notifications\Notification\InviteReply
|
||||
*
|
||||
*
|
||||
* Calendar access by sharees
|
||||
* ==========================
|
||||
*
|
||||
* As mentioned earlier, shared calendars must now also be returned for
|
||||
* getCalendarsForUser for sharees. A few things change though.
|
||||
*
|
||||
* The following properties must be specified:
|
||||
*
|
||||
* 1. {http://calendarserver.org/ns/}shared-url
|
||||
*
|
||||
* This property MUST contain the url to the original calendar, that is.. the
|
||||
* path to the calendar from the owner.
|
||||
*
|
||||
* 2. {http://sabredav.org/ns}owner-principal
|
||||
*
|
||||
* This is a url to to the principal who is sharing the calendar.
|
||||
*
|
||||
* 3. {http://sabredav.org/ns}read-only
|
||||
*
|
||||
* This should be either 0 or 1, depending on if the user has read-only or
|
||||
* read-write access to the calendar.
|
||||
*
|
||||
* Only when this is done, the calendar will correctly be marked as a calendar
|
||||
* that's shared to him, thus allowing clients to display the correct interface
|
||||
* and ACL enforcement.
|
||||
*
|
||||
* If a sharee deletes their calendar, only their instance of the calendar
|
||||
* should be deleted, the original should still exists.
|
||||
* Pretty much any 'dead' WebDAV properties on these shared calendars should be
|
||||
* specific to a user. This means that if the displayname is changed by a
|
||||
* sharee, the original is not affected. This is also true for:
|
||||
* * The description
|
||||
* * The color
|
||||
* * The order
|
||||
* * And any other dead properties.
|
||||
*
|
||||
* Properties like a ctag should not be different for multiple instances of the
|
||||
* calendar.
|
||||
*
|
||||
* Lastly, objects *within* calendars should also have user-specific data. The
|
||||
* two things that are user-specific are:
|
||||
* * VALARM objects
|
||||
* * The TRANSP property
|
||||
*
|
||||
* This _also_ implies that if a VALARM is deleted by a sharee for some event,
|
||||
* this has no effect on the original VALARM.
|
||||
*
|
||||
* Understandably, the this last requirement is one of the hardest.
|
||||
* Realisticly, I can see people ignoring this part of the spec, but that could
|
||||
* cause a different set of issues.
|
||||
*
|
||||
*
|
||||
* Publishing
|
||||
* ==========
|
||||
*
|
||||
* When a user publishes a url, the server should generate a 'publish url'.
|
||||
* This is a read-only url, anybody can use to consume the calendar feed.
|
||||
*
|
||||
* Calendars are in one of two states:
|
||||
* * published
|
||||
* * unpublished
|
||||
*
|
||||
* If a calendar is published, the following property should be returned
|
||||
* for each calendar in getCalendarsForUser.
|
||||
*
|
||||
* {http://calendarserver.org/ns/}publish-url
|
||||
*
|
||||
* This element should contain a {DAV:}href element, which points to the
|
||||
* public url that does not require authentication. Unlike every other href,
|
||||
* this url must be absolute.
|
||||
*
|
||||
* Ideally, the following property is always returned
|
||||
*
|
||||
* {http://calendarserver.org/ns/}pre-publish-url
|
||||
*
|
||||
* This property should contain the url that the calendar _would_ have, if it
|
||||
* were to be published. iCal uses this to display the url, before the user
|
||||
* will actually publish it.
|
||||
*
|
||||
*
|
||||
* Selectively disabling publish or share feature
|
||||
* ==============================================
|
||||
*
|
||||
* If Sabre\CalDAV\Property\AllowedSharingModes is returned from
|
||||
* getCalendarsForUser, this allows the server to specify whether either sharing,
|
||||
* or publishing is supported.
|
||||
*
|
||||
* This allows a client to determine in advance which features are available,
|
||||
* and update the interface appropriately. If this property is not returned by
|
||||
* the backend, the SharingPlugin automatically injects it and assumes both
|
||||
* features are available.
|
||||
* 1. Return shared calendars for users.
|
||||
* 2. For every calendar, return calendar-resource-uri. This strings is a URI or
|
||||
* relative URI reference that must be unique for every calendar, but
|
||||
* identical for every instance of the same shared calenar.
|
||||
* 3. For every calenar, you must return a share-access element. This element
|
||||
* should contain one of the Sabre\DAV\Sharing\Plugin:ACCESS_* contants and
|
||||
* indicates the access level the user has.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
interface SharingSupport extends NotificationSupport {
|
||||
interface SharingSupport extends BackendInterface {
|
||||
|
||||
/**
|
||||
* Updates the list of shares.
|
||||
*
|
||||
* The first array is a list of people that are to be added to the
|
||||
* calendar.
|
||||
*
|
||||
* Every element in the add array has the following properties:
|
||||
* * href - A url. Usually a mailto: address
|
||||
* * commonName - Usually a first and last name, or false
|
||||
* * summary - A description of the share, can also be false
|
||||
* * readOnly - A boolean value
|
||||
*
|
||||
* Every element in the remove array is just the address string.
|
||||
*
|
||||
* Note that if the calendar is currently marked as 'not shared' by and
|
||||
* this method is called, the calendar should be 'upgraded' to a shared
|
||||
* calendar.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param array $add
|
||||
* @param array $remove
|
||||
* @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
|
||||
* @return void
|
||||
*/
|
||||
function updateShares($calendarId, array $add, array $remove);
|
||||
function updateInvites($calendarId, array $sharees);
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
* Every item in the returned list must be a Sharee object with at
|
||||
* least the following properties set:
|
||||
* $href
|
||||
* $shareAccess
|
||||
* $inviteStatus
|
||||
*
|
||||
* This method may be called by either the original instance of the
|
||||
* calendar, as well as the shared instances. In the case of the shared
|
||||
* instances, it is perfectly acceptable to return an empty array in case
|
||||
* there are privacy concerns.
|
||||
* and optionally:
|
||||
* $properties
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @return array
|
||||
* @return \Sabre\DAV\Xml\Element\Sharee[]
|
||||
*/
|
||||
function getShares($calendarId);
|
||||
|
||||
/**
|
||||
* This method is called when a user replied to a request to share.
|
||||
*
|
||||
* If the user chose to accept the share, this method should return the
|
||||
* newly created calendar url.
|
||||
*
|
||||
* @param string href The sharee who is replying (often a mailto: address)
|
||||
* @param int status One of the SharingPlugin::STATUS_* constants
|
||||
* @param string $calendarUri The url to the calendar thats being shared
|
||||
* @param string $inReplyTo The unique id this message is a response to
|
||||
* @param string $summary A description of the reply
|
||||
* @return null|string
|
||||
*/
|
||||
function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null);
|
||||
function getInvites($calendarId);
|
||||
|
||||
/**
|
||||
* Publishes a calendar
|
||||
|
296
vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php
vendored
Normal file
296
vendor/sabre/dav/lib/CalDAV/Backend/SimplePDO.php
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Backend;
|
||||
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* Simple PDO CalDAV backend.
|
||||
*
|
||||
* This class is basically the most minmum example to get a caldav backend up
|
||||
* and running. This class uses the following schema (MySQL example):
|
||||
*
|
||||
* CREATE TABLE simple_calendars (
|
||||
* id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
* uri VARBINARY(200) NOT NULL,
|
||||
* principaluri VARBINARY(200) NOT NULL
|
||||
* );
|
||||
*
|
||||
* CREATE TABLE simple_calendarobjects (
|
||||
* id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
* calendarid INT UNSIGNED NOT NULL,
|
||||
* uri VARBINARY(200) NOT NULL,
|
||||
* calendardata MEDIUMBLOB
|
||||
* )
|
||||
*
|
||||
* To make this class work, you absolutely need to have the PropertyStorage
|
||||
* plugin enabled.
|
||||
*
|
||||
* @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 SimplePDO extends AbstractBackend {
|
||||
|
||||
/**
|
||||
* pdo
|
||||
*
|
||||
* @var \PDO
|
||||
*/
|
||||
protected $pdo;
|
||||
|
||||
/**
|
||||
* Creates the backend
|
||||
*
|
||||
* @param \PDO $pdo
|
||||
*/
|
||||
function __construct(\PDO $pdo) {
|
||||
|
||||
$this->pdo = $pdo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of calendars for a principal.
|
||||
*
|
||||
* Every project is an array with the following keys:
|
||||
* * id, a unique id that will be used by other functions to modify the
|
||||
* calendar. This can be the same as the uri or a database key.
|
||||
* * uri. This is just the 'base uri' or 'filename' of the calendar.
|
||||
* * principaluri. The owner of the calendar. Almost always the same as
|
||||
* principalUri passed to this method.
|
||||
*
|
||||
* Furthermore it can contain webdav properties in clark notation. A very
|
||||
* common one is '{DAV:}displayname'.
|
||||
*
|
||||
* Many clients also require:
|
||||
* {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set
|
||||
* For this property, you can just return an instance of
|
||||
* Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet.
|
||||
*
|
||||
* If you return {http://sabredav.org/ns}read-only and set the value to 1,
|
||||
* ACL will automatically be put in read-only mode.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @return array
|
||||
*/
|
||||
function getCalendarsForUser($principalUri) {
|
||||
|
||||
// Making fields a comma-delimited list
|
||||
$stmt = $this->pdo->prepare("SELECT id, uri FROM simple_calendars WHERE principaluri = ? ORDER BY id ASC");
|
||||
$stmt->execute([$principalUri]);
|
||||
|
||||
$calendars = [];
|
||||
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
|
||||
$calendars[] = [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'principaluri' => $principalUri,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return $calendars;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new calendar for a principal.
|
||||
*
|
||||
* If the creation was a success, an id must be returned that can be used
|
||||
* to reference this calendar in other methods, such as updateCalendar.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @param string $calendarUri
|
||||
* @param array $properties
|
||||
* @return string
|
||||
*/
|
||||
function createCalendar($principalUri, $calendarUri, array $properties) {
|
||||
|
||||
$stmt = $this->pdo->prepare("INSERT INTO simple_calendars (principaluri, uri) VALUES (?, ?)");
|
||||
$stmt->execute([$principalUri, $calendarUri]);
|
||||
|
||||
return $this->pdo->lastInsertId();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a calendar and all it's objects
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @return void
|
||||
*/
|
||||
function deleteCalendar($calendarId) {
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM simple_calendars WHERE id = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all calendar objects within a calendar.
|
||||
*
|
||||
* Every item contains an array with the following keys:
|
||||
* * calendardata - The iCalendar-compatible calendar data
|
||||
* * uri - a unique key which will be used to construct the uri. This can
|
||||
* be any arbitrary string, but making sure it ends with '.ics' is a
|
||||
* good idea. This is only the basename, or filename, not the full
|
||||
* path.
|
||||
* * lastmodified - a timestamp of the last modification time
|
||||
* * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
|
||||
* ' "abcdef"')
|
||||
* * size - The size of the calendar objects, in bytes.
|
||||
* * component - optional, a string containing the type of object, such
|
||||
* as 'vevent' or 'vtodo'. If specified, this will be used to populate
|
||||
* the Content-Type header.
|
||||
*
|
||||
* Note that the etag is optional, but it's highly encouraged to return for
|
||||
* speed reasons.
|
||||
*
|
||||
* The calendardata is also optional. If it's not returned
|
||||
* 'getCalendarObject' will be called later, which *is* expected to return
|
||||
* calendardata.
|
||||
*
|
||||
* If neither etag or size are specified, the calendardata will be
|
||||
* used/fetched to determine these numbers. If both are specified the
|
||||
* amount of times this is needed is reduced by a great degree.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @return array
|
||||
*/
|
||||
function getCalendarObjects($calendarId) {
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT id, uri, calendardata FROM simple_calendarobjects WHERE calendarid = ?');
|
||||
$stmt->execute([$calendarId]);
|
||||
|
||||
$result = [];
|
||||
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
|
||||
$result[] = [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'etag' => '"' . md5($row['calendardata']) . '"',
|
||||
'calendarid' => $calendarId,
|
||||
'size' => strlen($row['calendardata']),
|
||||
'calendardata' => $row['calendardata'],
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information from a single calendar object, based on it's object
|
||||
* uri.
|
||||
*
|
||||
* The object uri is only the basename, or filename and not a full path.
|
||||
*
|
||||
* The returned array must have the same keys as getCalendarObjects. The
|
||||
* 'calendardata' object is required here though, while it's not required
|
||||
* for getCalendarObjects.
|
||||
*
|
||||
* This method must return null if the object did not exist.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param string $objectUri
|
||||
* @return array|null
|
||||
*/
|
||||
function getCalendarObject($calendarId, $objectUri) {
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT id, uri, calendardata FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute([$calendarId, $objectUri]);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$row) return null;
|
||||
|
||||
return [
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'etag' => '"' . md5($row['calendardata']) . '"',
|
||||
'calendarid' => $calendarId,
|
||||
'size' => strlen($row['calendardata']),
|
||||
'calendardata' => $row['calendardata'],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new calendar object.
|
||||
*
|
||||
* The object uri is only the basename, or filename and not a full path.
|
||||
*
|
||||
* It is possible return an etag from this function, which will be used in
|
||||
* the response to this PUT request. Note that the ETag must be surrounded
|
||||
* by double-quotes.
|
||||
*
|
||||
* However, you should only really return this ETag if you don't mangle the
|
||||
* calendar-data. If the result of a subsequent GET to this object is not
|
||||
* the exact same as this request body, you should omit the ETag.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param string $objectUri
|
||||
* @param string $calendarData
|
||||
* @return string|null
|
||||
*/
|
||||
function createCalendarObject($calendarId, $objectUri, $calendarData) {
|
||||
|
||||
$stmt = $this->pdo->prepare('INSERT INTO simple_calendarobjects (calendarid, uri, calendardata) VALUES (?,?,?)');
|
||||
$stmt->execute([
|
||||
$calendarId,
|
||||
$objectUri,
|
||||
$calendarData
|
||||
]);
|
||||
|
||||
return '"' . md5($calendarData) . '"';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing calendarobject, based on it's uri.
|
||||
*
|
||||
* The object uri is only the basename, or filename and not a full path.
|
||||
*
|
||||
* It is possible return an etag from this function, which will be used in
|
||||
* the response to this PUT request. Note that the ETag must be surrounded
|
||||
* by double-quotes.
|
||||
*
|
||||
* However, you should only really return this ETag if you don't mangle the
|
||||
* calendar-data. If the result of a subsequent GET to this object is not
|
||||
* the exact same as this request body, you should omit the ETag.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param string $objectUri
|
||||
* @param string $calendarData
|
||||
* @return string|null
|
||||
*/
|
||||
function updateCalendarObject($calendarId, $objectUri, $calendarData) {
|
||||
|
||||
$stmt = $this->pdo->prepare('UPDATE simple_calendarobjects SET calendardata = ? WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute([$calendarData, $calendarId, $objectUri]);
|
||||
|
||||
return '"' . md5($calendarData) . '"';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing calendar object.
|
||||
*
|
||||
* The object uri is only the basename, or filename and not a full path.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param string $objectUri
|
||||
* @return void
|
||||
*/
|
||||
function deleteCalendarObject($calendarId, $objectUri) {
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute([$calendarId, $objectUri]);
|
||||
|
||||
}
|
||||
|
||||
}
|
63
vendor/sabre/dav/lib/CalDAV/Calendar.php
vendored
63
vendor/sabre/dav/lib/CalDAV/Calendar.php
vendored
@ -18,6 +18,8 @@ use Sabre\DAV\PropPatch;
|
||||
*/
|
||||
class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, DAV\IMultiGet {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* This is an array with calendar information
|
||||
*
|
||||
@ -86,7 +88,7 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
|
||||
|
||||
foreach ($this->calendarInfo as $propName => $propValue) {
|
||||
|
||||
if ($propName[0] === '{')
|
||||
if (!is_null($propValue) && $propName[0] === '{')
|
||||
$response[$propName] = $this->calendarInfo[$propName];
|
||||
|
||||
}
|
||||
@ -227,7 +229,7 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
|
||||
/**
|
||||
* Returns the last modification date as a unix timestamp.
|
||||
*
|
||||
* @return void
|
||||
* @return null
|
||||
*/
|
||||
function getLastModified() {
|
||||
|
||||
@ -248,19 +250,6 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
@ -360,50 +349,6 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
$default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet();
|
||||
|
||||
// We need to inject 'read-free-busy' in the tree, aggregated under
|
||||
// {DAV:}read.
|
||||
foreach ($default['aggregates'] as &$agg) {
|
||||
|
||||
if ($agg['privilege'] !== '{DAV:}read') continue;
|
||||
|
||||
$agg['aggregates'][] = [
|
||||
'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy',
|
||||
];
|
||||
|
||||
}
|
||||
return $default;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
|
64
vendor/sabre/dav/lib/CalDAV/CalendarHome.php
vendored
64
vendor/sabre/dav/lib/CalDAV/CalendarHome.php
vendored
@ -22,6 +22,8 @@ use Sabre\HTTP\URLUtil;
|
||||
*/
|
||||
class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* CalDAV backend
|
||||
*
|
||||
@ -147,11 +149,7 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
foreach ($this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']) as $calendar) {
|
||||
if ($calendar['uri'] === $name) {
|
||||
if ($this->caldavBackend instanceof Backend\SharingSupport) {
|
||||
if (isset($calendar['{http://calendarserver.org/ns/}shared-url'])) {
|
||||
return new SharedCalendar($this->caldavBackend, $calendar);
|
||||
} else {
|
||||
return new ShareableCalendar($this->caldavBackend, $calendar);
|
||||
}
|
||||
return new SharedCalendar($this->caldavBackend, $calendar);
|
||||
} else {
|
||||
return new Calendar($this->caldavBackend, $calendar);
|
||||
}
|
||||
@ -198,11 +196,7 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
$objs = [];
|
||||
foreach ($calendars as $calendar) {
|
||||
if ($this->caldavBackend instanceof Backend\SharingSupport) {
|
||||
if (isset($calendar['{http://calendarserver.org/ns/}shared-url'])) {
|
||||
$objs[] = new SharedCalendar($this->caldavBackend, $calendar);
|
||||
} else {
|
||||
$objs[] = new ShareableCalendar($this->caldavBackend, $calendar);
|
||||
}
|
||||
$objs[] = new SharedCalendar($this->caldavBackend, $calendar);
|
||||
} else {
|
||||
$objs[] = new Calendar($this->caldavBackend, $calendar);
|
||||
}
|
||||
@ -278,11 +272,9 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
* Returns the owner of the calendar home.
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
* @return string
|
||||
*/
|
||||
function getOwner() {
|
||||
|
||||
@ -290,19 +282,6 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
@ -348,37 +327,6 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when a user replied to a request to share.
|
||||
|
61
vendor/sabre/dav/lib/CalDAV/CalendarObject.php
vendored
61
vendor/sabre/dav/lib/CalDAV/CalendarObject.php
vendored
@ -11,6 +11,8 @@ namespace Sabre\CalDAV;
|
||||
*/
|
||||
class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\DAVACL\IACL {
|
||||
|
||||
use \Sabre\DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* Sabre\CalDAV\Backend\BackendInterface
|
||||
*
|
||||
@ -191,19 +193,6 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
@ -226,22 +215,12 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
|
||||
// The default ACL
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
@ -255,36 +234,4 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new \Sabre\DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
22
vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php
vendored
22
vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php
vendored
@ -170,13 +170,13 @@ class ICSExportPlugin extends DAV\ServerPlugin {
|
||||
protected function generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, ResponseInterface $response) {
|
||||
|
||||
$calDataProp = '{' . Plugin::NS_CALDAV . '}calendar-data';
|
||||
$calendarNode = $this->server->tree->getNodeForPath($path);
|
||||
|
||||
$blobs = [];
|
||||
if ($start || $end || $componentType) {
|
||||
|
||||
// If there was a start or end filter, we need to enlist
|
||||
// calendarQuery for speed.
|
||||
$calendarNode = $this->server->tree->getNodeForPath($path);
|
||||
$queryResult = $calendarNode->calendarQuery([
|
||||
'name' => 'VCALENDAR',
|
||||
'comp-filters' => [
|
||||
@ -246,17 +246,29 @@ class ICSExportPlugin extends DAV\ServerPlugin {
|
||||
$mergedCalendar = $mergedCalendar->expand($start, $end, $calendarTimeZone);
|
||||
}
|
||||
|
||||
$response->setHeader('Content-Type', $format);
|
||||
$filenameExtension = '.ics';
|
||||
|
||||
switch ($format) {
|
||||
case 'text/calendar' :
|
||||
$mergedCalendar = $mergedCalendar->serialize();
|
||||
$filenameExtension = '.ics';
|
||||
break;
|
||||
case 'application/calendar+json' :
|
||||
$mergedCalendar = json_encode($mergedCalendar->jsonSerialize());
|
||||
$filenameExtension = '.json';
|
||||
break;
|
||||
}
|
||||
|
||||
$filename = preg_replace(
|
||||
'/[^a-zA-Z0-9-_ ]/um',
|
||||
'',
|
||||
$calendarNode->getName()
|
||||
);
|
||||
$filename .= '-' . date('Y-m-d') . $filenameExtension;
|
||||
|
||||
$response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
|
||||
$response->setHeader('Content-Type', $format);
|
||||
|
||||
$response->setStatus(200);
|
||||
$response->setBody($mergedCalendar);
|
||||
|
||||
@ -272,11 +284,11 @@ class ICSExportPlugin extends DAV\ServerPlugin {
|
||||
function mergeObjects(array $properties, array $inputObjects) {
|
||||
|
||||
$calendar = new VObject\Component\VCalendar();
|
||||
$calendar->version = '2.0';
|
||||
$calendar->VERSION = '2.0';
|
||||
if (DAV\Server::$exposeVersion) {
|
||||
$calendar->prodid = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN';
|
||||
$calendar->PRODID = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN';
|
||||
} else {
|
||||
$calendar->prodid = '-//SabreDAV//SabreDAV//EN';
|
||||
$calendar->PRODID = '-//SabreDAV//SabreDAV//EN';
|
||||
}
|
||||
if (isset($properties['{DAV:}displayname'])) {
|
||||
$calendar->{'X-WR-CALNAME'} = $properties['{DAV:}displayname'];
|
||||
|
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* This interface represents a Calendar that can be shared with other users.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
interface IShareableCalendar extends ICalendar {
|
||||
|
||||
/**
|
||||
* Updates the list of shares.
|
||||
*
|
||||
* The first array is a list of people that are to be added to the
|
||||
* calendar.
|
||||
*
|
||||
* Every element in the add array has the following properties:
|
||||
* * href - A url. Usually a mailto: address
|
||||
* * commonName - Usually a first and last name, or false
|
||||
* * summary - A description of the share, can also be false
|
||||
* * readOnly - A boolean value
|
||||
*
|
||||
* Every element in the remove array is just the address string.
|
||||
*
|
||||
* @param array $add
|
||||
* @param array $remove
|
||||
* @return void
|
||||
*/
|
||||
function updateShares(array $add, array $remove);
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getShares();
|
||||
|
||||
}
|
30
vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php
vendored
30
vendor/sabre/dav/lib/CalDAV/ISharedCalendar.php
vendored
@ -2,6 +2,8 @@
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\DAV\Sharing\ISharedNode;
|
||||
|
||||
/**
|
||||
* This interface represents a Calendar that is shared by a different user.
|
||||
*
|
||||
@ -9,28 +11,16 @@ namespace Sabre\CalDAV;
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
interface ISharedCalendar extends ICalendar {
|
||||
interface ISharedCalendar extends ISharedNode {
|
||||
|
||||
/**
|
||||
* This method should return the url of the owners' copy of the shared
|
||||
* calendar.
|
||||
* Marks this calendar as published.
|
||||
*
|
||||
* @return string
|
||||
* Publishing a calendar should automatically create a read-only, public,
|
||||
* subscribable calendar.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
function getSharedUrl();
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getShares();
|
||||
|
||||
function setPublishStatus($value);
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ use Sabre\DAVACL;
|
||||
*/
|
||||
class Collection extends DAV\Collection implements ICollection, DAVACL\IACL {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* The notification backend
|
||||
*
|
||||
@ -96,78 +98,4 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getACL() {
|
||||
|
||||
return [
|
||||
[
|
||||
'principal' => $this->getOwner(),
|
||||
'privilege' => '{DAV:}read',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'principal' => $this->getOwner(),
|
||||
'privilege' => '{DAV:}write',
|
||||
'protected' => true,
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's as an array argument.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\NotImplemented('Updating ACLs is not implemented here');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ use Sabre\DAVACL;
|
||||
*/
|
||||
class Node extends DAV\File implements INode, DAVACL\IACL {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* The notification backend
|
||||
*
|
||||
@ -116,78 +118,4 @@ class Node extends DAV\File implements INode, DAVACL\IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getACL() {
|
||||
|
||||
return [
|
||||
[
|
||||
'principal' => $this->getOwner(),
|
||||
'privilege' => '{DAV:}read',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'principal' => $this->getOwner(),
|
||||
'privilege' => '{DAV:}write',
|
||||
'protected' => true,
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's as an array argument.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\NotImplemented('Updating ACLs is not implemented here');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
113
vendor/sabre/dav/lib/CalDAV/Plugin.php
vendored
113
vendor/sabre/dav/lib/CalDAV/Plugin.php
vendored
@ -5,8 +5,9 @@ namespace Sabre\CalDAV;
|
||||
use DateTimeZone;
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAV\Exception\BadRequest;
|
||||
use Sabre\DAV\INode;
|
||||
use Sabre\DAV\MkCol;
|
||||
use Sabre\DAV\Xml\Property\Href;
|
||||
use Sabre\DAV\Xml\Property\LocalHref;
|
||||
use Sabre\DAVACL;
|
||||
use Sabre\VObject;
|
||||
use Sabre\HTTP;
|
||||
@ -186,6 +187,7 @@ class Plugin extends DAV\ServerPlugin {
|
||||
$server->on('beforeCreateFile', [$this, 'beforeCreateFile']);
|
||||
$server->on('beforeWriteContent', [$this, 'beforeWriteContent']);
|
||||
$server->on('afterMethod:GET', [$this, 'httpAfterGET']);
|
||||
$server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']);
|
||||
|
||||
$server->xml->namespaceMap[self::NS_CALDAV] = 'cal';
|
||||
$server->xml->namespaceMap[self::NS_CALENDARSERVER] = 'cs';
|
||||
@ -233,9 +235,10 @@ class Plugin extends DAV\ServerPlugin {
|
||||
*
|
||||
* @param string $reportName
|
||||
* @param mixed $report
|
||||
* @param mixed $path
|
||||
* @return bool
|
||||
*/
|
||||
function report($reportName, $report) {
|
||||
function report($reportName, $report, $path) {
|
||||
|
||||
switch ($reportName) {
|
||||
case '{' . self::NS_CALDAV . '}calendar-multiget' :
|
||||
@ -341,7 +344,7 @@ class Plugin extends DAV\ServerPlugin {
|
||||
|
||||
$calendarHomePath = $this->getCalendarHomeForPrincipal($principalUrl);
|
||||
if (is_null($calendarHomePath)) return null;
|
||||
return new Href($calendarHomePath . '/');
|
||||
return new LocalHref($calendarHomePath . '/');
|
||||
|
||||
});
|
||||
// The calendar-user-address-set property is basically mapped to
|
||||
@ -349,7 +352,7 @@ class Plugin extends DAV\ServerPlugin {
|
||||
$propFind->handle('{' . self::NS_CALDAV . '}calendar-user-address-set', function() use ($node) {
|
||||
$addresses = $node->getAlternateUriSet();
|
||||
$addresses[] = $this->server->getBaseUri() . $node->getPrincipalUrl() . '/';
|
||||
return new Href($addresses, false);
|
||||
return new LocalHref($addresses);
|
||||
});
|
||||
// For some reason somebody thought it was a good idea to add
|
||||
// another one of these properties. We're supporting it too.
|
||||
@ -394,8 +397,8 @@ class Plugin extends DAV\ServerPlugin {
|
||||
|
||||
}
|
||||
|
||||
$propFind->set($propRead, new Href($readList));
|
||||
$propFind->set($propWrite, new Href($writeList));
|
||||
$propFind->set($propRead, new LocalHref($readList));
|
||||
$propFind->set($propWrite, new LocalHref($writeList));
|
||||
|
||||
}
|
||||
|
||||
@ -821,11 +824,7 @@ class Plugin extends DAV\ServerPlugin {
|
||||
$data = stream_get_contents($data);
|
||||
}
|
||||
|
||||
$before = md5($data);
|
||||
// Converting the data to unicode, if needed.
|
||||
$data = DAV\StringUtil::ensureUTF8($data);
|
||||
|
||||
if ($before !== md5($data)) $modified = true;
|
||||
$before = $data;
|
||||
|
||||
try {
|
||||
|
||||
@ -865,7 +864,7 @@ class Plugin extends DAV\ServerPlugin {
|
||||
}
|
||||
|
||||
$foundType = null;
|
||||
$foundUID = null;
|
||||
|
||||
foreach ($vobj->getComponents() as $component) {
|
||||
switch ($component->name) {
|
||||
case 'VTIMEZONE' :
|
||||
@ -873,31 +872,59 @@ class Plugin extends DAV\ServerPlugin {
|
||||
case 'VEVENT' :
|
||||
case 'VTODO' :
|
||||
case 'VJOURNAL' :
|
||||
if (is_null($foundType)) {
|
||||
$foundType = $component->name;
|
||||
if (!in_array($foundType, $supportedComponents)) {
|
||||
throw new Exception\InvalidComponentType('This calendar only supports ' . implode(', ', $supportedComponents) . '. We found a ' . $foundType);
|
||||
}
|
||||
if (!isset($component->UID)) {
|
||||
throw new DAV\Exception\BadRequest('Every ' . $component->name . ' component must have an UID');
|
||||
}
|
||||
$foundUID = (string)$component->UID;
|
||||
} else {
|
||||
if ($foundType !== $component->name) {
|
||||
throw new DAV\Exception\BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType);
|
||||
}
|
||||
if ($foundUID !== (string)$component->UID) {
|
||||
throw new DAV\Exception\BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
|
||||
}
|
||||
}
|
||||
$foundType = $component->name;
|
||||
break;
|
||||
default :
|
||||
throw new DAV\Exception\BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!$foundType || !in_array($foundType, $supportedComponents)) {
|
||||
throw new Exception\InvalidComponentType('iCalendar objects must at least have a component of type ' . implode(', ', $supportedComponents));
|
||||
}
|
||||
|
||||
$options = VObject\Node::PROFILE_CALDAV;
|
||||
$prefer = $this->server->getHTTPPrefer();
|
||||
|
||||
if ($prefer['handling'] !== 'strict') {
|
||||
$options |= VObject\Node::REPAIR;
|
||||
}
|
||||
|
||||
$messages = $vobj->validate($options);
|
||||
|
||||
$highestLevel = 0;
|
||||
$warningMessage = null;
|
||||
|
||||
// $messages contains a list of problems with the vcard, along with
|
||||
// their severity.
|
||||
foreach ($messages as $message) {
|
||||
|
||||
if ($message['level'] > $highestLevel) {
|
||||
// Recording the highest reported error level.
|
||||
$highestLevel = $message['level'];
|
||||
$warningMessage = $message['message'];
|
||||
}
|
||||
switch ($message['level']) {
|
||||
|
||||
case 1 :
|
||||
// Level 1 means that there was a problem, but it was repaired.
|
||||
$modified = true;
|
||||
break;
|
||||
case 2 :
|
||||
// Level 2 means a warning, but not critical
|
||||
break;
|
||||
case 3 :
|
||||
// Level 3 means a critical error
|
||||
throw new DAV\Exception\UnsupportedMediaType('Validation error in iCalendar: ' . $message['message']);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if ($warningMessage) {
|
||||
$response->setHeader(
|
||||
'X-Sabre-Ew-Gross',
|
||||
'iCalendar validation warning: ' . $warningMessage
|
||||
);
|
||||
}
|
||||
if (!$foundType)
|
||||
throw new DAV\Exception\BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
|
||||
|
||||
// We use an extra variable to allow event handles to tell us wether
|
||||
// the object was modified or not.
|
||||
@ -917,12 +944,12 @@ class Plugin extends DAV\ServerPlugin {
|
||||
]
|
||||
);
|
||||
|
||||
if ($subModified) {
|
||||
if ($modified || $subModified) {
|
||||
// An event handler told us that it modified the object.
|
||||
$data = $vobj->serialize();
|
||||
|
||||
// Using md5 to figure out if there was an *actual* change.
|
||||
if (!$modified && $before !== md5($data)) {
|
||||
if (!$modified && strcmp($data, $before) !== 0) {
|
||||
$modified = true;
|
||||
}
|
||||
|
||||
@ -933,6 +960,22 @@ class Plugin extends DAV\ServerPlugin {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is triggered whenever a subsystem reqeuests the privileges
|
||||
* that are supported on a particular node.
|
||||
*
|
||||
* @param INode $node
|
||||
* @param array $supportedPrivilegeSet
|
||||
*/
|
||||
function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) {
|
||||
|
||||
if ($node instanceof ICalendar) {
|
||||
$supportedPrivilegeSet['{DAV:}read']['aggregates']['{' . self::NS_CALDAV . '}read-free-busy'] = [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to generate HTML output for the
|
||||
|
64
vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php
vendored
64
vendor/sabre/dav/lib/CalDAV/Schedule/Inbox.php
vendored
@ -17,6 +17,8 @@ use Sabre\VObject;
|
||||
*/
|
||||
class Inbox extends DAV\Collection implements IInbox {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* CalDAV backend
|
||||
*
|
||||
@ -118,19 +120,6 @@ class Inbox extends DAV\Collection implements IInbox {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
@ -167,12 +156,7 @@ class Inbox extends DAV\Collection implements IInbox {
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver-invite',
|
||||
'principal' => '{DAV:}authenticated',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver-reply',
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver',
|
||||
'principal' => '{DAV:}authenticated',
|
||||
'protected' => true,
|
||||
],
|
||||
@ -180,48 +164,6 @@ class Inbox extends DAV\Collection implements IInbox {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('You\'re not allowed to update the ACL');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
$ns = '{' . CalDAV\Plugin::NS_CALDAV . '}';
|
||||
|
||||
$default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet();
|
||||
$default['aggregates'][] = [
|
||||
'privilege' => $ns . 'schedule-deliver',
|
||||
'aggregates' => [
|
||||
['privilege' => $ns . 'schedule-deliver-invite'],
|
||||
['privilege' => $ns . 'schedule-deliver-reply'],
|
||||
],
|
||||
];
|
||||
return $default;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
|
69
vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php
vendored
69
vendor/sabre/dav/lib/CalDAV/Schedule/Outbox.php
vendored
@ -19,6 +19,8 @@ use Sabre\DAVACL;
|
||||
*/
|
||||
class Outbox extends DAV\Collection implements IOutbox {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* The principal Uri
|
||||
*
|
||||
@ -74,19 +76,6 @@ class Outbox extends DAV\Collection implements IOutbox {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
@ -103,12 +92,7 @@ class Outbox extends DAV\Collection implements IOutbox {
|
||||
|
||||
return [
|
||||
[
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent',
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
@ -118,12 +102,7 @@ class Outbox extends DAV\Collection implements IOutbox {
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent',
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
@ -141,44 +120,4 @@ class Outbox extends DAV\Collection implements IOutbox {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('You\'re not allowed to update the ACL');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
$default = DAVACL\Plugin::getDefaultSupportedPrivilegeSet();
|
||||
$default['aggregates'][] = [
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-query-freebusy',
|
||||
];
|
||||
$default['aggregates'][] = [
|
||||
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-post-vevent',
|
||||
];
|
||||
|
||||
return $default;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
107
vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php
vendored
107
vendor/sabre/dav/lib/CalDAV/Schedule/Plugin.php
vendored
@ -5,10 +5,12 @@ namespace Sabre\CalDAV\Schedule;
|
||||
use DateTimeZone;
|
||||
use Sabre\DAV\Server;
|
||||
use Sabre\DAV\ServerPlugin;
|
||||
use Sabre\DAV\Sharing;
|
||||
use Sabre\DAV\PropFind;
|
||||
use Sabre\DAV\PropPatch;
|
||||
use Sabre\DAV\INode;
|
||||
use Sabre\DAV\Xml\Property\Href;
|
||||
use Sabre\DAV\Xml\Property\LocalHref;
|
||||
use Sabre\HTTP\RequestInterface;
|
||||
use Sabre\HTTP\ResponseInterface;
|
||||
use Sabre\VObject;
|
||||
@ -100,12 +102,13 @@ class Plugin extends ServerPlugin {
|
||||
function initialize(Server $server) {
|
||||
|
||||
$this->server = $server;
|
||||
$server->on('method:POST', [$this, 'httpPost']);
|
||||
$server->on('propFind', [$this, 'propFind']);
|
||||
$server->on('propPatch', [$this, 'propPatch']);
|
||||
$server->on('calendarObjectChange', [$this, 'calendarObjectChange']);
|
||||
$server->on('beforeUnbind', [$this, 'beforeUnbind']);
|
||||
$server->on('schedule', [$this, 'scheduleLocalDelivery']);
|
||||
$server->on('method:POST', [$this, 'httpPost']);
|
||||
$server->on('propFind', [$this, 'propFind']);
|
||||
$server->on('propPatch', [$this, 'propPatch']);
|
||||
$server->on('calendarObjectChange', [$this, 'calendarObjectChange']);
|
||||
$server->on('beforeUnbind', [$this, 'beforeUnbind']);
|
||||
$server->on('schedule', [$this, 'scheduleLocalDelivery']);
|
||||
$server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']);
|
||||
|
||||
$ns = '{' . self::NS_CALDAV . '}';
|
||||
|
||||
@ -215,7 +218,7 @@ class Plugin extends ServerPlugin {
|
||||
}
|
||||
$outboxPath = $calendarHomePath . '/outbox/';
|
||||
|
||||
return new Href($outboxPath);
|
||||
return new LocalHref($outboxPath);
|
||||
|
||||
});
|
||||
// schedule-inbox-URL property
|
||||
@ -227,7 +230,7 @@ class Plugin extends ServerPlugin {
|
||||
}
|
||||
$inboxPath = $calendarHomePath . '/inbox/';
|
||||
|
||||
return new Href($inboxPath);
|
||||
return new LocalHref($inboxPath);
|
||||
|
||||
});
|
||||
|
||||
@ -245,18 +248,28 @@ class Plugin extends ServerPlugin {
|
||||
|
||||
$result = $this->server->getPropertiesForPath($calendarHomePath, [
|
||||
'{DAV:}resourcetype',
|
||||
'{DAV:}share-access',
|
||||
$sccs,
|
||||
], 1);
|
||||
|
||||
foreach ($result as $child) {
|
||||
if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar') || $child[200]['{DAV:}resourcetype']->is('{http://calendarserver.org/ns/}shared')) {
|
||||
// Node is either not a calendar or a shared instance.
|
||||
if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar')) {
|
||||
// Node is either not a calendar
|
||||
continue;
|
||||
}
|
||||
if (isset($child[200]['{DAV:}share-access'])) {
|
||||
$shareAccess = $child[200]['{DAV:}share-access']->getValue();
|
||||
if ($shareAccess !== Sharing\Plugin::ACCESS_NOTSHARED && $shareAccess !== Sharing\Plugin::ACCESS_SHAREDOWNER) {
|
||||
// Node is a shared node, not owned by the relevant
|
||||
// user.
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!isset($child[200][$sccs]) || in_array('VEVENT', $child[200][$sccs]->getValue())) {
|
||||
// Either there is no supported-calendar-component-set
|
||||
// (which is fine) or we found one that supports VEVENT.
|
||||
return new Href($child['href']);
|
||||
return new LocalHref($child['href']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,7 +505,7 @@ class Plugin extends ServerPlugin {
|
||||
}
|
||||
|
||||
if (!$aclPlugin->checkPrivileges($inboxPath, $caldavNS . $privilege, DAVACL\Plugin::R_PARENT, false)) {
|
||||
$iTipMessage->scheduleStatus = '3.8;organizer did not have the ' . $privilege . ' privilege on the attendees inbox';
|
||||
$iTipMessage->scheduleStatus = '3.8;insufficient privileges: ' . $privilege . ' is required on the recipient schedule inbox.';
|
||||
return;
|
||||
}
|
||||
|
||||
@ -560,6 +573,65 @@ class Plugin extends ServerPlugin {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is triggered whenever a subsystem requests the privileges
|
||||
* that 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) {
|
||||
|
||||
$ns = '{' . self::NS_CALDAV . '}';
|
||||
if ($node instanceof IOutbox) {
|
||||
$supportedPrivilegeSet[$ns . 'schedule-send'] = [
|
||||
'abstract' => false,
|
||||
'aggregates' => [
|
||||
$ns . 'schedule-send-invite' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
$ns . 'schedule-send-reply' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
$ns . 'schedule-send-freebusy' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
// Privilege from an earlier scheduling draft, but still
|
||||
// used by some clients.
|
||||
$ns . 'schedule-post-vevent' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
if ($node instanceof IInbox) {
|
||||
$supportedPrivilegeSet[$ns . 'schedule-deliver'] = [
|
||||
'abstract' => false,
|
||||
'aggregates' => [
|
||||
$ns . 'schedule-deliver-invite' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
$ns . 'schedule-deliver-reply' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
$ns . 'schedule-query-freebusy' => [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method looks at an old iCalendar object, a new iCalendar object and
|
||||
* starts sending scheduling messages based on the changes.
|
||||
@ -647,7 +719,7 @@ class Plugin extends ServerPlugin {
|
||||
/**
|
||||
* This method handles POST requests to the schedule-outbox.
|
||||
*
|
||||
* Currently, two types of requests are support:
|
||||
* Currently, two types of requests are supported:
|
||||
* * FREEBUSY requests from RFC 6638
|
||||
* * Simple iTIP messages from draft-desruisseaux-caldav-sched-04
|
||||
*
|
||||
@ -699,7 +771,7 @@ class Plugin extends ServerPlugin {
|
||||
|
||||
if ($componentType === 'VFREEBUSY' && $method === 'REQUEST') {
|
||||
|
||||
$acl && $acl->checkPrivileges($outboxPath, '{' . self::NS_CALDAV . '}schedule-query-freebusy');
|
||||
$acl && $acl->checkPrivileges($outboxPath, '{' . self::NS_CALDAV . '}schedule-send-freebusy');
|
||||
$this->handleFreeBusyRequest($outboxNode, $vObject, $request, $response);
|
||||
|
||||
// Destroy circular references so PHP can GC the object.
|
||||
@ -727,7 +799,7 @@ class Plugin extends ServerPlugin {
|
||||
protected function handleFreeBusyRequest(IOutbox $outbox, VObject\Component $vObject, RequestInterface $request, ResponseInterface $response) {
|
||||
|
||||
$vFreeBusy = $vObject->VFREEBUSY;
|
||||
$organizer = $vFreeBusy->organizer;
|
||||
$organizer = $vFreeBusy->ORGANIZER;
|
||||
|
||||
$organizer = (string)$organizer;
|
||||
|
||||
@ -863,6 +935,9 @@ class Plugin extends ServerPlugin {
|
||||
$homeSet = $result[0][200][$caldavNS . 'calendar-home-set']->getHref();
|
||||
$inboxUrl = $result[0][200][$caldavNS . 'schedule-inbox-URL']->getHref();
|
||||
|
||||
// Do we have permission?
|
||||
$aclPlugin->checkPrivileges($inboxUrl, $caldavNS . 'schedule-query-freebusy');
|
||||
|
||||
// Grabbing the calendar list
|
||||
$objects = [];
|
||||
$calendarTimeZone = new DateTimeZone('UTC');
|
||||
@ -882,8 +957,6 @@ class Plugin extends ServerPlugin {
|
||||
continue;
|
||||
}
|
||||
|
||||
$aclPlugin->checkPrivileges($homeSet . $node->getName(), $caldavNS . 'read-free-busy');
|
||||
|
||||
if (isset($props[$ctz])) {
|
||||
$vtimezoneObj = VObject\Reader::read($props[$ctz]);
|
||||
$calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone();
|
||||
|
@ -134,22 +134,12 @@ class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements IScheduli
|
||||
// The default ACL
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->objectData['principaluri'],
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => '{DAV:}owner',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->objectData['principaluri'],
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->objectData['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->objectData['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
|
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* This object represents a CalDAV calendar that can be shared with other
|
||||
* users.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class ShareableCalendar extends Calendar implements IShareableCalendar {
|
||||
|
||||
/**
|
||||
* Updates the list of shares.
|
||||
*
|
||||
* The first array is a list of people that are to be added to the
|
||||
* calendar.
|
||||
*
|
||||
* Every element in the add array has the following properties:
|
||||
* * href - A url. Usually a mailto: address
|
||||
* * commonName - Usually a first and last name, or false
|
||||
* * summary - A description of the share, can also be false
|
||||
* * readOnly - A boolean value
|
||||
*
|
||||
* Every element in the remove array is just the address string.
|
||||
*
|
||||
* @param array $add
|
||||
* @param array $remove
|
||||
* @return void
|
||||
*/
|
||||
function updateShares(array $add, array $remove) {
|
||||
|
||||
$this->caldavBackend->updateShares($this->calendarInfo['id'], $add, $remove);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getShares() {
|
||||
|
||||
return $this->caldavBackend->getShares($this->calendarInfo['id']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this calendar as published.
|
||||
*
|
||||
* Publishing a calendar should automatically create a read-only, public,
|
||||
* subscribable calendar.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
function setPublishStatus($value) {
|
||||
|
||||
$this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value);
|
||||
|
||||
}
|
||||
|
||||
}
|
235
vendor/sabre/dav/lib/CalDAV/SharedCalendar.php
vendored
235
vendor/sabre/dav/lib/CalDAV/SharedCalendar.php
vendored
@ -2,6 +2,8 @@
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\DAV\Sharing\Plugin as SPlugin;
|
||||
|
||||
/**
|
||||
* This object represents a CalDAV calendar that is shared by a different user.
|
||||
*
|
||||
@ -12,50 +14,84 @@ namespace Sabre\CalDAV;
|
||||
class SharedCalendar extends Calendar implements ISharedCalendar {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Returns the 'access level' for the instance of this shared resource.
|
||||
*
|
||||
* @param Backend\BackendInterface $caldavBackend
|
||||
* @param array $calendarInfo
|
||||
* The value should be one of the Sabre\DAV\Sharing\Plugin::ACCESS_
|
||||
* constants.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) {
|
||||
function getShareAccess() {
|
||||
|
||||
$required = [
|
||||
'{http://calendarserver.org/ns/}shared-url',
|
||||
'{http://sabredav.org/ns}owner-principal',
|
||||
'{http://sabredav.org/ns}read-only',
|
||||
];
|
||||
foreach ($required as $r) {
|
||||
if (!isset($calendarInfo[$r])) {
|
||||
throw new \InvalidArgumentException('The ' . $r . ' property must be specified for SharedCalendar(s)');
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($caldavBackend, $calendarInfo);
|
||||
return isset($this->calendarInfo['share-access']) ? $this->calendarInfo['share-access'] : SPlugin::ACCESS_NOTSHARED;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should return the url of the owners' copy of the shared
|
||||
* calendar.
|
||||
* 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 getSharedUrl() {
|
||||
function getShareResourceUri() {
|
||||
|
||||
return $this->calendarInfo['{http://calendarserver.org/ns/}shared-url'];
|
||||
return $this->calendarInfo['share-resource-uri'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
* Updates the list of sharees.
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
* Every item must be a Sharee object.
|
||||
*
|
||||
* @return string|null
|
||||
* @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
|
||||
* @return void
|
||||
*/
|
||||
function getOwner() {
|
||||
function updateInvites(array $sharees) {
|
||||
|
||||
return $this->calendarInfo['{http://sabredav.org/ns}owner-principal'];
|
||||
$this->caldavBackend->updateInvites($this->calendarInfo['id'], $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() {
|
||||
|
||||
return $this->caldavBackend->getInvites($this->calendarInfo['id']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this calendar as published.
|
||||
*
|
||||
* Publishing a calendar should automatically create a read-only, public,
|
||||
* subscribable calendar.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
function setPublishStatus($value) {
|
||||
|
||||
$this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value);
|
||||
|
||||
}
|
||||
|
||||
@ -73,32 +109,72 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
|
||||
*/
|
||||
function getACL() {
|
||||
|
||||
// The top-level ACL only contains access information for the true
|
||||
// owner of the calendar, so we need to add the information for the
|
||||
// sharee.
|
||||
$acl = parent::getACL();
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
if ($this->calendarInfo['{http://sabredav.org/ns}read-only']) {
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write-properties',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
} else {
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl = [];
|
||||
|
||||
switch ($this->getShareAccess()) {
|
||||
case SPlugin::ACCESS_NOTSHARED :
|
||||
case SPlugin::ACCESS_SHAREDOWNER :
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}share',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}share',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
];
|
||||
// No break intentional!
|
||||
case SPlugin::ACCESS_READWRITE :
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
];
|
||||
// No break intentional!
|
||||
case SPlugin::ACCESS_READ :
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write-properties',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write-properties',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy',
|
||||
'principal' => '{DAV:}authenticated',
|
||||
'protected' => true,
|
||||
];
|
||||
break;
|
||||
}
|
||||
return $acl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method returns the ACL's for calendar objects in this calendar.
|
||||
* The result of this method automatically gets passed to the
|
||||
@ -108,41 +184,46 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
|
||||
*/
|
||||
function getChildACL() {
|
||||
|
||||
$acl = parent::getChildACL();
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl = [];
|
||||
|
||||
if (!$this->calendarInfo['{http://sabredav.org/ns}read-only']) {
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
switch ($this->getShareAccess()) {
|
||||
case SPlugin::ACCESS_NOTSHARED :
|
||||
// No break intentional
|
||||
case SPlugin::ACCESS_SHAREDOWNER :
|
||||
// No break intentional
|
||||
case SPlugin::ACCESS_READWRITE:
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
];
|
||||
// No break intentional
|
||||
case SPlugin::ACCESS_READ:
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
];
|
||||
$acl[] = [
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
];
|
||||
break;
|
||||
}
|
||||
|
||||
return $acl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getShares() {
|
||||
|
||||
return $this->caldavBackend->getShares($this->calendarInfo['id']);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
106
vendor/sabre/dav/lib/CalDAV/SharingPlugin.php
vendored
106
vendor/sabre/dav/lib/CalDAV/SharingPlugin.php
vendored
@ -4,6 +4,7 @@ namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAV\Xml\Property\Href;
|
||||
use Sabre\DAV\Xml\Property\LocalHref;
|
||||
use Sabre\HTTP\RequestInterface;
|
||||
use Sabre\HTTP\ResponseInterface;
|
||||
|
||||
@ -25,15 +26,6 @@ use Sabre\HTTP\ResponseInterface;
|
||||
*/
|
||||
class SharingPlugin extends DAV\ServerPlugin {
|
||||
|
||||
/**
|
||||
* These are the various status constants used by sharing-messages.
|
||||
*/
|
||||
const STATUS_ACCEPTED = 1;
|
||||
const STATUS_DECLINED = 2;
|
||||
const STATUS_DELETED = 3;
|
||||
const STATUS_NORESPONSE = 4;
|
||||
const STATUS_INVALID = 5;
|
||||
|
||||
/**
|
||||
* Reference to SabreDAV server object.
|
||||
*
|
||||
@ -83,7 +75,10 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
function initialize(DAV\Server $server) {
|
||||
|
||||
$this->server = $server;
|
||||
$server->resourceTypeMapping['Sabre\\CalDAV\\ISharedCalendar'] = '{' . Plugin::NS_CALENDARSERVER . '}shared';
|
||||
|
||||
if (is_null($this->server->getPlugin('sharing'))) {
|
||||
throw new \LogicException('The generic "sharing" plugin must be loaded before the caldav sharing plugin. Call $server->addPlugin(new \Sabre\DAV\Sharing\Plugin()); before this one.');
|
||||
}
|
||||
|
||||
array_push(
|
||||
$this->server->protectedProperties,
|
||||
@ -114,24 +109,8 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
*/
|
||||
function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) {
|
||||
|
||||
if ($node instanceof IShareableCalendar) {
|
||||
|
||||
$propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) {
|
||||
return new Xml\Property\Invite(
|
||||
$node->getShares()
|
||||
);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if ($node instanceof ISharedCalendar) {
|
||||
|
||||
$propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}shared-url', function() use ($node) {
|
||||
return new Href(
|
||||
$node->getSharedUrl()
|
||||
);
|
||||
});
|
||||
|
||||
$propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) {
|
||||
|
||||
// Fetching owner information
|
||||
@ -158,7 +137,7 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
}
|
||||
|
||||
return new Xml\Property\Invite(
|
||||
$node->getShares(),
|
||||
$node->getInvites(),
|
||||
$ownerInfo
|
||||
);
|
||||
|
||||
@ -179,10 +158,18 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
*/
|
||||
function propFindLate(DAV\PropFind $propFind, DAV\INode $node) {
|
||||
|
||||
if ($node instanceof IShareableCalendar) {
|
||||
if ($node instanceof ISharedCalendar) {
|
||||
$shareAccess = $node->getShareAccess();
|
||||
if ($rt = $propFind->get('{DAV:}resourcetype')) {
|
||||
if (count($node->getShares()) > 0) {
|
||||
$rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner');
|
||||
switch ($shareAccess) {
|
||||
case \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER :
|
||||
$rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner');
|
||||
break;
|
||||
case \Sabre\DAV\Sharing\Plugin::ACCESS_READ :
|
||||
case \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE :
|
||||
$rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared');
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
$propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function() {
|
||||
@ -211,21 +198,24 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
function propPatch($path, DAV\PropPatch $propPatch) {
|
||||
|
||||
$node = $this->server->tree->getNodeForPath($path);
|
||||
if (!$node instanceof IShareableCalendar)
|
||||
if (!$node instanceof ISharedCalendar)
|
||||
return;
|
||||
|
||||
$propPatch->handle('{DAV:}resourcetype', function($value) use ($node) {
|
||||
if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) return false;
|
||||
$shares = $node->getShares();
|
||||
$remove = [];
|
||||
foreach ($shares as $share) {
|
||||
$remove[] = $share['href'];
|
||||
}
|
||||
$node->updateShares([], $remove);
|
||||
if ($node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER || $node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_NOTSHARED) {
|
||||
|
||||
return true;
|
||||
$propPatch->handle('{DAV:}resourcetype', function($value) use ($node) {
|
||||
if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) return false;
|
||||
$shares = $node->getInvites();
|
||||
foreach ($shares as $share) {
|
||||
$share->access = DAV\Sharing\Plugin::ACCESS_NOACCESS;
|
||||
}
|
||||
$node->updateInvites($shares);
|
||||
|
||||
});
|
||||
return true;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -267,26 +257,12 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
|
||||
switch ($documentType) {
|
||||
|
||||
// Dealing with the 'share' document, which modified invitees on a
|
||||
// calendar.
|
||||
// Both the DAV:share-resource and CALENDARSERVER:share requests
|
||||
// behave identically.
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}share' :
|
||||
|
||||
// We can only deal with IShareableCalendar objects
|
||||
if (!$node instanceof IShareableCalendar) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->server->transactionType = 'post-calendar-share';
|
||||
|
||||
// Getting ACL info
|
||||
$acl = $this->server->getPlugin('acl');
|
||||
|
||||
// If there's no ACL support, we allow everything
|
||||
if ($acl) {
|
||||
$acl->checkPrivileges($path, '{DAV:}write');
|
||||
}
|
||||
|
||||
$node->updateShares($message->set, $message->remove);
|
||||
$sharingPlugin = $this->server->getPlugin('sharing');
|
||||
$sharingPlugin->shareResource($path, $message->sharees);
|
||||
|
||||
$response->setStatus(200);
|
||||
// Adding this because sending a response body may cause issues,
|
||||
@ -328,11 +304,11 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
$response->setHeader('X-Sabre-Status', 'everything-went-well');
|
||||
|
||||
if ($url) {
|
||||
$writer = $this->server->xml->getWriter($this->server->getBaseUri());
|
||||
$writer = $this->server->xml->getWriter();
|
||||
$writer->openMemory();
|
||||
$writer->startDocument();
|
||||
$writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}shared-as');
|
||||
$writer->write(new Href($url));
|
||||
$writer->write(new LocalHref($url));
|
||||
$writer->endElement();
|
||||
$response->setHeader('Content-Type', 'application/xml');
|
||||
$response->setBody($writer->outputMemory());
|
||||
@ -345,7 +321,7 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar' :
|
||||
|
||||
// We can only deal with IShareableCalendar objects
|
||||
if (!$node instanceof IShareableCalendar) {
|
||||
if (!$node instanceof ISharedCalendar) {
|
||||
return;
|
||||
}
|
||||
$this->server->transactionType = 'post-publish-calendar';
|
||||
@ -355,7 +331,7 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
|
||||
// If there's no ACL support, we allow everything
|
||||
if ($acl) {
|
||||
$acl->checkPrivileges($path, '{DAV:}write');
|
||||
$acl->checkPrivileges($path, '{DAV:}share');
|
||||
}
|
||||
|
||||
$node->setPublishStatus(true);
|
||||
@ -373,7 +349,7 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar' :
|
||||
|
||||
// We can only deal with IShareableCalendar objects
|
||||
if (!$node instanceof IShareableCalendar) {
|
||||
if (!$node instanceof ISharedCalendar) {
|
||||
return;
|
||||
}
|
||||
$this->server->transactionType = 'post-unpublish-calendar';
|
||||
@ -383,7 +359,7 @@ class SharingPlugin extends DAV\ServerPlugin {
|
||||
|
||||
// If there's no ACL support, we allow everything
|
||||
if ($acl) {
|
||||
$acl->checkPrivileges($path, '{DAV:}write');
|
||||
$acl->checkPrivileges($path, '{DAV:}share');
|
||||
}
|
||||
|
||||
$node->setPublishStatus(false);
|
||||
|
@ -5,8 +5,8 @@ namespace Sabre\CalDAV\Subscriptions;
|
||||
use Sabre\DAV\Collection;
|
||||
use Sabre\DAV\Xml\Property\Href;
|
||||
use Sabre\DAV\PropPatch;
|
||||
use Sabre\DAV\Exception\MethodNotAllowed;
|
||||
use Sabre\DAVACL\IACL;
|
||||
use Sabre\DAVACL\ACLTrait;
|
||||
use Sabre\CalDAV\Backend\SubscriptionSupport;
|
||||
|
||||
/**
|
||||
@ -20,6 +20,8 @@ use Sabre\CalDAV\Backend\SubscriptionSupport;
|
||||
*/
|
||||
class Subscription extends Collection implements ISubscription, IACL {
|
||||
|
||||
use ACLTrait;
|
||||
|
||||
/**
|
||||
* caldavBackend
|
||||
*
|
||||
@ -144,7 +146,7 @@ class Subscription extends Collection implements ISubscription, IACL {
|
||||
* The Server class will filter out the extra.
|
||||
*
|
||||
* @param array $properties
|
||||
* @return void
|
||||
* @return array
|
||||
*/
|
||||
function getProperties($properties) {
|
||||
|
||||
@ -154,7 +156,7 @@ class Subscription extends Collection implements ISubscription, IACL {
|
||||
|
||||
switch ($prop) {
|
||||
case '{http://calendarserver.org/ns/}source' :
|
||||
$r[$prop] = new Href($this->subscriptionInfo['source'], false);
|
||||
$r[$prop] = new Href($this->subscriptionInfo['source']);
|
||||
break;
|
||||
default :
|
||||
if (array_key_exists($prop, $this->subscriptionInfo)) {
|
||||
@ -182,19 +184,6 @@ class Subscription extends Collection implements ISubscription, IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal.
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
@ -211,22 +200,12 @@ class Subscription extends Collection implements ISubscription, IACL {
|
||||
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
],
|
||||
@ -239,36 +218,4 @@ class Subscription extends Collection implements ISubscription, IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL.
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See \Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Sabre\CalDAV\Xml\Notification;
|
||||
use Sabre\Xml\Writer;
|
||||
use Sabre\CalDAV\SharingPlugin as SharingPlugin;
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* This class represents the cs:invite-notification notification element.
|
||||
@ -210,16 +211,10 @@ class Invite implements NotificationInterface {
|
||||
|
||||
switch ($this->type) {
|
||||
|
||||
case SharingPlugin::STATUS_ACCEPTED :
|
||||
case DAV\Sharing\Plugin::INVITE_ACCEPTED :
|
||||
$writer->writeElement($cs . 'invite-accepted');
|
||||
break;
|
||||
case SharingPlugin::STATUS_DECLINED :
|
||||
$writer->writeElement($cs . 'invite-declined');
|
||||
break;
|
||||
case SharingPlugin::STATUS_DELETED :
|
||||
$writer->writeElement($cs . 'invite-deleted');
|
||||
break;
|
||||
case SharingPlugin::STATUS_NORESPONSE :
|
||||
case DAV\Sharing\Plugin::INVITE_NORESPONSE :
|
||||
$writer->writeElement($cs . 'invite-noresponse');
|
||||
break;
|
||||
|
||||
|
@ -5,6 +5,7 @@ namespace Sabre\CalDAV\Xml\Notification;
|
||||
use Sabre\Xml\Writer;
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\CalDAV\SharingPlugin;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* This class represents the cs:invite-reply notification element.
|
||||
@ -162,10 +163,10 @@ class InviteReply implements NotificationInterface {
|
||||
|
||||
switch ($this->type) {
|
||||
|
||||
case SharingPlugin::STATUS_ACCEPTED :
|
||||
case DAV\Sharing\Plugin::INVITE_ACCEPTED :
|
||||
$writer->writeElement($cs . 'invite-accepted');
|
||||
break;
|
||||
case SharingPlugin::STATUS_DECLINED :
|
||||
case DAV\Sharing\Plugin::INVITE_DECLINED :
|
||||
$writer->writeElement($cs . 'invite-declined');
|
||||
break;
|
||||
|
||||
|
209
vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php
vendored
209
vendor/sabre/dav/lib/CalDAV/Xml/Property/Invite.php
vendored
@ -2,11 +2,10 @@
|
||||
|
||||
namespace Sabre\CalDAV\Xml\Property;
|
||||
|
||||
use Sabre\Xml\Element;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\XmlSerializable;
|
||||
use Sabre\Xml\Writer;
|
||||
use Sabre\CalDAV\Plugin;
|
||||
use Sabre\CalDAV\SharingPlugin;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* Invite property
|
||||
@ -20,53 +19,23 @@ use Sabre\CalDAV\SharingPlugin;
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Invite implements Element {
|
||||
class Invite implements XmlSerializable {
|
||||
|
||||
/**
|
||||
* The list of users a calendar has been shared to.
|
||||
*
|
||||
* @var array
|
||||
* @var Sharee[]
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* The organizer contains information about the person who shared the
|
||||
* object.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $organizer;
|
||||
protected $sharees;
|
||||
|
||||
/**
|
||||
* Creates the property.
|
||||
*
|
||||
* Users is an array. Each element of the array has the following
|
||||
* properties:
|
||||
*
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first and lastname for a user.
|
||||
* * status - One of the SharingPlugin::STATUS_* constants.
|
||||
* * readOnly - true or false
|
||||
* * summary - Optional, description of the share
|
||||
*
|
||||
* The organizer key is optional to specify. It's only useful when a
|
||||
* 'sharee' requests the sharing information.
|
||||
*
|
||||
* The organizer may have the following properties:
|
||||
* * href - Often a mailto: address.
|
||||
* * commonName - Optional human-readable name.
|
||||
* * firstName - Optional first name.
|
||||
* * lastName - Optional last name.
|
||||
*
|
||||
* If you wonder why these two structures are so different, I guess a
|
||||
* valid answer is that the current spec is still a draft.
|
||||
*
|
||||
* @param array $users
|
||||
* @param Sharee[] $sharees
|
||||
*/
|
||||
function __construct(array $users, array $organizer = null) {
|
||||
function __construct(array $sharees) {
|
||||
|
||||
$this->users = $users;
|
||||
$this->organizer = $organizer;
|
||||
$this->sharees = $sharees;
|
||||
|
||||
}
|
||||
|
||||
@ -77,7 +46,7 @@ class Invite implements Element {
|
||||
*/
|
||||
function getValue() {
|
||||
|
||||
return $this->users;
|
||||
return $this->sharees;
|
||||
|
||||
}
|
||||
|
||||
@ -104,149 +73,55 @@ class Invite implements Element {
|
||||
|
||||
$cs = '{' . Plugin::NS_CALENDARSERVER . '}';
|
||||
|
||||
if (!is_null($this->organizer)) {
|
||||
foreach ($this->sharees as $sharee) {
|
||||
|
||||
$writer->startElement($cs . 'organizer');
|
||||
$writer->writeElement('{DAV:}href', $this->organizer['href']);
|
||||
|
||||
if (isset($this->organizer['commonName']) && $this->organizer['commonName']) {
|
||||
$writer->writeElement($cs . 'common-name', $this->organizer['commonName']);
|
||||
}
|
||||
if (isset($this->organizer['firstName']) && $this->organizer['firstName']) {
|
||||
$writer->writeElement($cs . 'first-name', $this->organizer['firstName']);
|
||||
}
|
||||
if (isset($this->organizer['lastName']) && $this->organizer['lastName']) {
|
||||
$writer->writeElement($cs . 'last-name', $this->organizer['lastName']);
|
||||
}
|
||||
$writer->endElement(); // organizer
|
||||
|
||||
}
|
||||
|
||||
foreach ($this->users as $user) {
|
||||
|
||||
$writer->startElement($cs . 'user');
|
||||
$writer->writeElement('{DAV:}href', $user['href']);
|
||||
if (isset($user['commonName']) && $user['commonName']) {
|
||||
$writer->writeElement($cs . 'common-name', $user['commonName']);
|
||||
}
|
||||
switch ($user['status']) {
|
||||
|
||||
case SharingPlugin::STATUS_ACCEPTED :
|
||||
$writer->writeElement($cs . 'invite-accepted');
|
||||
break;
|
||||
case SharingPlugin::STATUS_DECLINED :
|
||||
$writer->writeElement($cs . 'invite-declined');
|
||||
break;
|
||||
case SharingPlugin::STATUS_NORESPONSE :
|
||||
$writer->writeElement($cs . 'invite-noresponse');
|
||||
break;
|
||||
case SharingPlugin::STATUS_INVALID :
|
||||
$writer->writeElement($cs . 'invite-invalid');
|
||||
break;
|
||||
}
|
||||
|
||||
$writer->startElement($cs . 'access');
|
||||
if ($user['readOnly']) {
|
||||
$writer->writeElement($cs . 'read');
|
||||
if ($sharee->access === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER) {
|
||||
$writer->startElement($cs . 'organizer');
|
||||
} else {
|
||||
$writer->writeElement($cs . 'read-write');
|
||||
}
|
||||
$writer->endElement(); // access
|
||||
$writer->startElement($cs . 'user');
|
||||
|
||||
if (isset($user['summary']) && $user['summary']) {
|
||||
$writer->writeElement($cs . 'summary', $user['summary']);
|
||||
}
|
||||
|
||||
$writer->endElement(); //user
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
$cs = '{' . Plugin::NS_CALENDARSERVER . '}';
|
||||
|
||||
$users = [];
|
||||
|
||||
foreach ($reader->parseInnerTree() as $elem) {
|
||||
|
||||
if ($elem['name'] !== $cs . 'user')
|
||||
continue;
|
||||
|
||||
$user = [
|
||||
'href' => null,
|
||||
'commonName' => null,
|
||||
'readOnly' => null,
|
||||
'summary' => null,
|
||||
'status' => null,
|
||||
];
|
||||
|
||||
foreach ($elem['value'] as $userElem) {
|
||||
|
||||
switch ($userElem['name']) {
|
||||
case $cs . 'invite-accepted' :
|
||||
$user['status'] = SharingPlugin::STATUS_ACCEPTED;
|
||||
switch ($sharee->inviteStatus) {
|
||||
case DAV\Sharing\Plugin::INVITE_ACCEPTED :
|
||||
$writer->writeElement($cs . 'invite-accepted');
|
||||
break;
|
||||
case $cs . 'invite-declined' :
|
||||
$user['status'] = SharingPlugin::STATUS_DECLINED;
|
||||
case DAV\Sharing\Plugin::INVITE_DECLINED :
|
||||
$writer->writeElement($cs . 'invite-declined');
|
||||
break;
|
||||
case $cs . 'invite-noresponse' :
|
||||
$user['status'] = SharingPlugin::STATUS_NORESPONSE;
|
||||
case DAV\Sharing\Plugin::INVITE_NORESPONSE :
|
||||
$writer->writeElement($cs . 'invite-noresponse');
|
||||
break;
|
||||
case $cs . 'invite-invalid' :
|
||||
$user['status'] = SharingPlugin::STATUS_INVALID;
|
||||
case DAV\Sharing\Plugin::INVITE_INVALID :
|
||||
$writer->writeElement($cs . 'invite-invalid');
|
||||
break;
|
||||
case '{DAV:}href' :
|
||||
$user['href'] = $userElem['value'];
|
||||
}
|
||||
|
||||
$writer->startElement($cs . 'access');
|
||||
switch ($sharee->access) {
|
||||
case DAV\Sharing\Plugin::ACCESS_READWRITE :
|
||||
$writer->writeElement($cs . 'read-write');
|
||||
break;
|
||||
case $cs . 'common-name' :
|
||||
$user['commonName'] = $userElem['value'];
|
||||
break;
|
||||
case $cs . 'access' :
|
||||
foreach ($userElem['value'] as $accessHref) {
|
||||
if ($accessHref['name'] === $cs . 'read') {
|
||||
$user['readOnly'] = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case $cs . 'summary' :
|
||||
$user['summary'] = $userElem['value'];
|
||||
case DAV\Sharing\Plugin::ACCESS_READ :
|
||||
$writer->writeElement($cs . 'read');
|
||||
break;
|
||||
|
||||
}
|
||||
$writer->endElement(); // access
|
||||
|
||||
}
|
||||
if (!$user['status']) {
|
||||
throw new \InvalidArgumentException('Every user must have one of cs:invite-accepted, cs:invite-declined, cs:invite-noresponse or cs:invite-invalid');
|
||||
}
|
||||
|
||||
$users[] = $user;
|
||||
$href = new \Sabre\DAV\Xml\Property\Href($sharee->href);
|
||||
$href->xmlSerialize($writer);
|
||||
|
||||
if (isset($sharee->properties['{DAV:}displayname'])) {
|
||||
$writer->writeElement($cs . 'common-name', $sharee->properties['{DAV:}displayname']);
|
||||
}
|
||||
if ($sharee->comment) {
|
||||
$writer->writeElement($cs . 'summary', $sharee->comment);
|
||||
}
|
||||
$writer->endElement(); // organizer or user
|
||||
|
||||
}
|
||||
|
||||
return new self($users);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ namespace Sabre\CalDAV\Xml\Property;
|
||||
|
||||
use Sabre\Xml\Element;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\Deserializer;
|
||||
use Sabre\Xml\Writer;
|
||||
use Sabre\Xml\Element\Elements;
|
||||
use Sabre\CalDAV\Plugin;
|
||||
|
||||
/**
|
||||
@ -116,23 +116,13 @@ class ScheduleCalendarTransp implements Element {
|
||||
*/
|
||||
static function xmlDeserialize(Reader $reader) {
|
||||
|
||||
$elems = Elements::xmlDeserialize($reader);
|
||||
$elems = Deserializer\enum($reader, Plugin::NS_CALDAV);
|
||||
|
||||
$value = null;
|
||||
|
||||
foreach ($elems as $elem) {
|
||||
switch ($elem) {
|
||||
case '{' . Plugin::NS_CALDAV . '}opaque' :
|
||||
$value = self::OPAQUE;
|
||||
break;
|
||||
case '{' . Plugin::NS_CALDAV . '}transparent' :
|
||||
$value = self::TRANSPARENT;
|
||||
break;
|
||||
}
|
||||
if (in_array('transparent', $elems)) {
|
||||
$value = self::TRANSPARENT;
|
||||
} else {
|
||||
$value = self::OPAQUE;
|
||||
}
|
||||
if (is_null($value))
|
||||
return null;
|
||||
|
||||
return new self($value);
|
||||
|
||||
}
|
||||
|
@ -2,12 +2,13 @@
|
||||
|
||||
namespace Sabre\CalDAV\Xml\Request;
|
||||
|
||||
use Sabre\CalDAV\Plugin;
|
||||
use Sabre\CalDAV\SharingPlugin;
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAV\Exception\BadRequest;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\XmlDeserializable;
|
||||
use Sabre\Xml\Element\KeyValue;
|
||||
use Sabre\DAV\Exception\BadRequest;
|
||||
use Sabre\CalDAV\Plugin;
|
||||
use Sabre\CalDAV\SharingPlugin;
|
||||
|
||||
/**
|
||||
* Invite-reply POST request parser
|
||||
@ -121,10 +122,10 @@ class InviteReply implements XmlDeserializable {
|
||||
}
|
||||
break;
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}invite-accepted' :
|
||||
$status = SharingPlugin::STATUS_ACCEPTED;
|
||||
$status = DAV\Sharing\Plugin::INVITE_ACCEPTED;
|
||||
break;
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}invite-declined' :
|
||||
$status = SharingPlugin::STATUS_DECLINED;
|
||||
$status = DAV\Sharing\Plugin::INVITE_DECLINED;
|
||||
break;
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}in-reply-to' :
|
||||
$inReplyTo = $value;
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
namespace Sabre\CalDAV\Xml\Request;
|
||||
|
||||
use Sabre\CalDAV\Plugin;
|
||||
use Sabre\DAV\Xml\Element\Sharee;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\XmlDeserializable;
|
||||
use Sabre\CalDAV\Plugin;
|
||||
|
||||
/**
|
||||
* Share POST request parser
|
||||
@ -20,37 +21,20 @@ use Sabre\CalDAV\Plugin;
|
||||
class Share implements XmlDeserializable {
|
||||
|
||||
/**
|
||||
* The list of new people added or updated.
|
||||
* The list of new people added or updated or removed from the share.
|
||||
*
|
||||
* Every element has the following keys:
|
||||
* 1. href - An email address
|
||||
* 2. commonName - Some name
|
||||
* 3. summary - An optional description of the share
|
||||
* 4. readOnly - true or false
|
||||
*
|
||||
* @var array
|
||||
* @var Sharee[]
|
||||
*/
|
||||
public $set = [];
|
||||
|
||||
/**
|
||||
* List of people removed from the share list.
|
||||
*
|
||||
* The list is a flat list of email addresses (including mailto:).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $remove = [];
|
||||
public $sharees = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $set
|
||||
* @param array $remove
|
||||
* @param Sharee[] $sharees
|
||||
*/
|
||||
function __construct(array $set, array $remove) {
|
||||
function __construct(array $sharees) {
|
||||
|
||||
$this->set = $set;
|
||||
$this->remove = $remove;
|
||||
$this->sharees = $sharees;
|
||||
|
||||
}
|
||||
|
||||
@ -77,13 +61,12 @@ class Share implements XmlDeserializable {
|
||||
*/
|
||||
static function xmlDeserialize(Reader $reader) {
|
||||
|
||||
$elems = $reader->parseInnerTree([
|
||||
$elems = $reader->parseGetElements([
|
||||
'{' . Plugin::NS_CALENDARSERVER . '}set' => 'Sabre\\Xml\\Element\\KeyValue',
|
||||
'{' . Plugin::NS_CALENDARSERVER . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
|
||||
]);
|
||||
|
||||
$set = [];
|
||||
$remove = [];
|
||||
$sharees = [];
|
||||
|
||||
foreach ($elems as $elem) {
|
||||
switch ($elem['name']) {
|
||||
@ -94,22 +77,34 @@ class Share implements XmlDeserializable {
|
||||
$sumElem = '{' . Plugin::NS_CALENDARSERVER . '}summary';
|
||||
$commonName = '{' . Plugin::NS_CALENDARSERVER . '}common-name';
|
||||
|
||||
$set[] = [
|
||||
$properties = [];
|
||||
if (isset($sharee[$commonName])) {
|
||||
$properties['{DAV:}displayname'] = $sharee[$commonName];
|
||||
}
|
||||
|
||||
$access = array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee)
|
||||
? \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE
|
||||
: \Sabre\DAV\Sharing\Plugin::ACCESS_READ;
|
||||
|
||||
$sharees[] = new Sharee([
|
||||
'href' => $sharee['{DAV:}href'],
|
||||
'commonName' => isset($sharee[$commonName]) ? $sharee[$commonName] : null,
|
||||
'summary' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
|
||||
'readOnly' => !array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee),
|
||||
];
|
||||
'properties' => $properties,
|
||||
'access' => $access,
|
||||
'comment' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null
|
||||
]);
|
||||
break;
|
||||
|
||||
case '{' . Plugin::NS_CALENDARSERVER . '}remove' :
|
||||
$remove[] = $elem['value']['{DAV:}href'];
|
||||
$sharees[] = new Sharee([
|
||||
'href' => $elem['value']['{DAV:}href'],
|
||||
'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS
|
||||
]);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return new self($set, $remove);
|
||||
return new self($sharees);
|
||||
|
||||
}
|
||||
|
||||
|
82
vendor/sabre/dav/lib/CardDAV/AddressBook.php
vendored
82
vendor/sabre/dav/lib/CardDAV/AddressBook.php
vendored
@ -16,6 +16,8 @@ use Sabre\DAVACL;
|
||||
*/
|
||||
class AddressBook extends DAV\Collection implements IAddressBook, DAV\IProperties, DAVACL\IACL, DAV\Sync\ISyncCollection, DAV\IMultiGet {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* This is an array with addressbook information
|
||||
*
|
||||
@ -236,48 +238,6 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getACL() {
|
||||
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ACL's for card nodes in this address book.
|
||||
@ -290,12 +250,7 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
|
||||
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
],
|
||||
@ -303,37 +258,6 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the current sync-token for this collection.
|
||||
|
76
vendor/sabre/dav/lib/CardDAV/AddressBookHome.php
vendored
76
vendor/sabre/dav/lib/CardDAV/AddressBookHome.php
vendored
@ -18,6 +18,8 @@ use Sabre\Uri;
|
||||
*/
|
||||
class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection, DAVACL\IACL {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* Principal uri
|
||||
*
|
||||
@ -186,78 +188,4 @@ class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
*
|
||||
* Each ACE has the following properties:
|
||||
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
|
||||
* currently the only supported privileges
|
||||
* * 'principal', a url to the principal who owns the node
|
||||
* * 'protected' (optional), indicating that this ACE is not allowed to
|
||||
* be updated.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getACL() {
|
||||
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->principalUri,
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->principalUri,
|
||||
'protected' => true,
|
||||
],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,12 +55,15 @@ interface BackendInterface {
|
||||
function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch);
|
||||
|
||||
/**
|
||||
* Creates a new address book
|
||||
* Creates a new address book.
|
||||
*
|
||||
* This method should return the id of the new address book. The id can be
|
||||
* in any format, including ints, strings, arrays or objects.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @param string $url Just the 'basename' of the url.
|
||||
* @param array $properties
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
function createAddressBook($principalUri, $url, array $properties);
|
||||
|
||||
|
9
vendor/sabre/dav/lib/CardDAV/Backend/PDO.php
vendored
9
vendor/sabre/dav/lib/CardDAV/Backend/PDO.php
vendored
@ -128,7 +128,7 @@ class PDO extends AbstractBackend implements SyncSupport {
|
||||
} else {
|
||||
$query .= ', ';
|
||||
}
|
||||
$query .= ' `' . $key . '` = :' . $key . ' ';
|
||||
$query .= ' ' . $key . ' = :' . $key . ' ';
|
||||
}
|
||||
$query .= ' WHERE id = :addressbookid';
|
||||
|
||||
@ -180,7 +180,9 @@ class PDO extends AbstractBackend implements SyncSupport {
|
||||
$query = 'INSERT INTO ' . $this->addressBooksTableName . ' (uri, displayname, description, principaluri, synctoken) VALUES (:uri, :displayname, :description, :principaluri, 1)';
|
||||
$stmt = $this->pdo->prepare($query);
|
||||
$stmt->execute($values);
|
||||
return $this->pdo->lastInsertId();
|
||||
return $this->pdo->lastInsertId(
|
||||
$this->addressBooksTableName . '_id_seq'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -230,6 +232,7 @@ class PDO extends AbstractBackend implements SyncSupport {
|
||||
$result = [];
|
||||
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$row['etag'] = '"' . $row['etag'] . '"';
|
||||
$row['lastmodified'] = (int)$row['lastmodified'];
|
||||
$result[] = $row;
|
||||
}
|
||||
return $result;
|
||||
@ -258,6 +261,7 @@ class PDO extends AbstractBackend implements SyncSupport {
|
||||
if (!$result) return false;
|
||||
|
||||
$result['etag'] = '"' . $result['etag'] . '"';
|
||||
$result['lastmodified'] = (int)$result['lastmodified'];
|
||||
return $result;
|
||||
|
||||
}
|
||||
@ -286,6 +290,7 @@ class PDO extends AbstractBackend implements SyncSupport {
|
||||
$result = [];
|
||||
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$row['etag'] = '"' . $row['etag'] . '"';
|
||||
$row['lastmodified'] = (int)$row['lastmodified'];
|
||||
$result[] = $row;
|
||||
}
|
||||
return $result;
|
||||
|
53
vendor/sabre/dav/lib/CardDAV/Card.php
vendored
53
vendor/sabre/dav/lib/CardDAV/Card.php
vendored
@ -14,6 +14,8 @@ use Sabre\DAV;
|
||||
*/
|
||||
class Card extends DAV\File implements ICard, DAVACL\IACL {
|
||||
|
||||
use DAVACL\ACLTrait;
|
||||
|
||||
/**
|
||||
* CardDAV backend
|
||||
*
|
||||
@ -181,18 +183,6 @@ class Card extends DAV\File implements ICard, DAVACL\IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ACE's for this node.
|
||||
@ -215,12 +205,7 @@ class Card extends DAV\File implements ICard, DAVACL\IACL {
|
||||
|
||||
return [
|
||||
[
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->addressBookInfo['principaluri'],
|
||||
'protected' => true,
|
||||
],
|
||||
[
|
||||
'privilege' => '{DAV:}write',
|
||||
'privilege' => '{DAV:}all',
|
||||
'principal' => $this->addressBookInfo['principaluri'],
|
||||
'protected' => true,
|
||||
],
|
||||
@ -228,36 +213,4 @@ class Card extends DAV\File implements ICard, DAVACL\IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
function setACL(array $acl) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre\DAVACL\Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
122
vendor/sabre/dav/lib/CardDAV/Plugin.php
vendored
122
vendor/sabre/dav/lib/CardDAV/Plugin.php
vendored
@ -4,7 +4,7 @@ namespace Sabre\CardDAV;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAV\Exception\ReportNotSupported;
|
||||
use Sabre\DAV\Xml\Property\Href;
|
||||
use Sabre\DAV\Xml\Property\LocalHref;
|
||||
use Sabre\DAVACL;
|
||||
use Sabre\HTTP;
|
||||
use Sabre\HTTP\RequestInterface;
|
||||
@ -156,11 +156,11 @@ class Plugin extends DAV\ServerPlugin {
|
||||
$path = $propFind->getPath();
|
||||
|
||||
$propFind->handle('{' . self::NS_CARDDAV . '}addressbook-home-set', function() use ($path) {
|
||||
return new Href($this->getAddressBookHomeForPrincipal($path) . '/');
|
||||
return new LocalHref($this->getAddressBookHomeForPrincipal($path) . '/');
|
||||
});
|
||||
|
||||
if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
|
||||
return new Href($this->directories);
|
||||
return new LocalHref($this->directories);
|
||||
});
|
||||
|
||||
}
|
||||
@ -334,12 +334,7 @@ class Plugin extends DAV\ServerPlugin {
|
||||
$data = stream_get_contents($data);
|
||||
}
|
||||
|
||||
$before = md5($data);
|
||||
|
||||
// Converting the data to unicode, if needed.
|
||||
$data = DAV\StringUtil::ensureUTF8($data);
|
||||
|
||||
if (md5($data) !== $before) $modified = true;
|
||||
$before = $data;
|
||||
|
||||
try {
|
||||
|
||||
@ -366,11 +361,56 @@ class Plugin extends DAV\ServerPlugin {
|
||||
throw new DAV\Exception\UnsupportedMediaType('This collection can only support vcard objects.');
|
||||
}
|
||||
|
||||
if (!isset($vobj->UID)) {
|
||||
// No UID in vcards is invalid, but we'll just add it in anyway.
|
||||
$vobj->add('UID', DAV\UUIDUtil::getUUID());
|
||||
$options = VObject\Node::PROFILE_CARDDAV;
|
||||
$prefer = $this->server->getHTTPPrefer();
|
||||
|
||||
if ($prefer['handling'] !== 'strict') {
|
||||
$options |= VObject\Node::REPAIR;
|
||||
}
|
||||
|
||||
$messages = $vobj->validate($options);
|
||||
|
||||
$highestLevel = 0;
|
||||
$warningMessage = null;
|
||||
|
||||
// $messages contains a list of problems with the vcard, along with
|
||||
// their severity.
|
||||
foreach ($messages as $message) {
|
||||
|
||||
if ($message['level'] > $highestLevel) {
|
||||
// Recording the highest reported error level.
|
||||
$highestLevel = $message['level'];
|
||||
$warningMessage = $message['message'];
|
||||
}
|
||||
|
||||
switch ($message['level']) {
|
||||
|
||||
case 1 :
|
||||
// Level 1 means that there was a problem, but it was repaired.
|
||||
$modified = true;
|
||||
break;
|
||||
case 2 :
|
||||
// Level 2 means a warning, but not critical
|
||||
break;
|
||||
case 3 :
|
||||
// Level 3 means a critical error
|
||||
throw new DAV\Exception\UnsupportedMediaType('Validation error in vCard: ' . $message['message']);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if ($warningMessage) {
|
||||
$this->server->httpResponse->setHeader(
|
||||
'X-Sabre-Ew-Gross',
|
||||
'vCard validation warning: ' . $warningMessage
|
||||
);
|
||||
|
||||
// Re-serializing object.
|
||||
$data = $vobj->serialize();
|
||||
$modified = true;
|
||||
if (!$modified && strcmp($data, $before) !== 0) {
|
||||
// This ensures that the system does not send an ETag back.
|
||||
$modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy circular references to PHP will GC the object.
|
||||
@ -803,33 +843,49 @@ class Plugin extends DAV\ServerPlugin {
|
||||
/**
|
||||
* Converts a vcard blob to a different version, or jcard.
|
||||
*
|
||||
* @param string $data
|
||||
* @param string|resource $data
|
||||
* @param string $target
|
||||
* @return string
|
||||
*/
|
||||
protected function convertVCard($data, $target) {
|
||||
|
||||
$data = VObject\Reader::read($data);
|
||||
switch ($target) {
|
||||
default :
|
||||
case 'vcard3' :
|
||||
$data = $data->convert(VObject\Document::VCARD30);
|
||||
$newResult = $data->serialize();
|
||||
break;
|
||||
case 'vcard4' :
|
||||
$data = $data->convert(VObject\Document::VCARD40);
|
||||
$newResult = $data->serialize();
|
||||
break;
|
||||
case 'jcard' :
|
||||
$data = $data->convert(VObject\Document::VCARD40);
|
||||
$newResult = json_encode($data->jsonSerialize());
|
||||
break;
|
||||
|
||||
if (is_resource($data)) {
|
||||
$data = stream_get_contents($data);
|
||||
}
|
||||
// Destroy circular references to PHP will GC the object.
|
||||
$data->destroy();
|
||||
$input = VObject\Reader::read($data);
|
||||
$output = null;
|
||||
try {
|
||||
|
||||
return $newResult;
|
||||
switch ($target) {
|
||||
default :
|
||||
case 'vcard3' :
|
||||
if ($input->getDocumentType() === VObject\Document::VCARD30) {
|
||||
// Do nothing
|
||||
return $data;
|
||||
}
|
||||
$output = $input->convert(VObject\Document::VCARD30);
|
||||
return $output->serialize();
|
||||
case 'vcard4' :
|
||||
if ($input->getDocumentType() === VObject\Document::VCARD40) {
|
||||
// Do nothing
|
||||
return $data;
|
||||
}
|
||||
$output = $input->convert(VObject\Document::VCARD40);
|
||||
return $output->serialize();
|
||||
case 'jcard' :
|
||||
$output = $input->convert(VObject\Document::VCARD40);
|
||||
return json_encode($output);
|
||||
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
||||
// Destroy circular references to PHP will GC the object.
|
||||
$input->destroy();
|
||||
if (!is_null($output)) {
|
||||
$output->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
28
vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php
vendored
28
vendor/sabre/dav/lib/CardDAV/VCFExportPlugin.php
vendored
@ -70,14 +70,34 @@ class VCFExportPlugin extends DAV\ServerPlugin {
|
||||
$aclPlugin->checkPrivileges($path, '{DAV:}read');
|
||||
}
|
||||
|
||||
$response->setHeader('Content-Type', 'text/directory');
|
||||
$response->setStatus(200);
|
||||
|
||||
$nodes = $this->server->getPropertiesForPath($path, [
|
||||
'{' . Plugin::NS_CARDDAV . '}address-data',
|
||||
], 1);
|
||||
|
||||
$response->setBody($this->generateVCF($nodes));
|
||||
$format = 'text/directory';
|
||||
|
||||
$output = null;
|
||||
$filenameExtension = null;
|
||||
|
||||
switch ($format) {
|
||||
case 'text/directory':
|
||||
$output = $this->generateVCF($nodes);
|
||||
$filenameExtension = '.vcf';
|
||||
break;
|
||||
}
|
||||
|
||||
$filename = preg_replace(
|
||||
'/[^a-zA-Z0-9-_ ]/um',
|
||||
'',
|
||||
$node->getName()
|
||||
);
|
||||
$filename .= '-' . date('Y-m-d') . $filenameExtension;
|
||||
|
||||
$response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
|
||||
$response->setHeader('Content-Type', $format);
|
||||
|
||||
$response->setStatus(200);
|
||||
$response->setBody($output);
|
||||
|
||||
// Returning false to break the event chain
|
||||
return false;
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class File extends AbstractDigest {
|
||||
/**
|
||||
* Creates the backend object.
|
||||
*
|
||||
* If the filename argument is passed in, it will parse out the specified file fist.
|
||||
* If the filename argument is passed in, it will parse out the specified file first.
|
||||
*
|
||||
* @param string|null $filename
|
||||
*/
|
||||
|
126
vendor/sabre/dav/lib/DAV/Auth/Plugin.php
vendored
126
vendor/sabre/dav/lib/DAV/Auth/Plugin.php
vendored
@ -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;
|
||||
@ -25,6 +24,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
|
||||
*/
|
||||
@ -107,27 +120,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
|
||||
*
|
||||
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
13
vendor/sabre/dav/lib/DAV/Browser/Plugin.php
vendored
13
vendor/sabre/dav/lib/DAV/Browser/Plugin.php
vendored
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
19
vendor/sabre/dav/lib/DAV/Client.php
vendored
19
vendor/sabre/dav/lib/DAV/Client.php
vendored
@ -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
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
40
vendor/sabre/dav/lib/DAV/CorePlugin.php
vendored
40
vendor/sabre/dav/lib/DAV/CorePlugin.php
vendored
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -904,6 +904,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.
|
||||
*
|
||||
|
6
vendor/sabre/dav/lib/DAV/FS/Directory.php
vendored
6
vendor/sabre/dav/lib/DAV/FS/Directory.php
vendored
@ -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)
|
||||
];
|
||||
|
||||
}
|
||||
|
10
vendor/sabre/dav/lib/DAV/FSExt/Directory.php
vendored
10
vendor/sabre/dav/lib/DAV/FSExt/Directory.php
vendored
@ -131,12 +131,7 @@ class Directory extends Node implements DAV\ICollection, DAV\IQuota, DAV\IMoveTa
|
||||
|
||||
foreach ($iterator as $entry) {
|
||||
|
||||
$node = $entry->getFilename();
|
||||
|
||||
if ($node === '.sabredav')
|
||||
continue;
|
||||
|
||||
$nodes[] = $this->getChild($node);
|
||||
$nodes[] = $this->getChild($entry->getFilename());
|
||||
|
||||
}
|
||||
return $nodes;
|
||||
@ -153,9 +148,6 @@ class Directory extends Node implements DAV\ICollection, DAV\IQuota, DAV\IMoveTa
|
||||
// Deleting all children
|
||||
foreach ($this->getChildren() as $child) $child->delete();
|
||||
|
||||
// Removing resource info, if its still around
|
||||
if (file_exists($this->path . '/.sabredav')) unlink($this->path . '/.sabredav');
|
||||
|
||||
// Removing the directory itself
|
||||
rmdir($this->path);
|
||||
|
||||
|
20
vendor/sabre/dav/lib/DAV/File.php
vendored
20
vendor/sabre/dav/lib/DAV/File.php
vendored
@ -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) {
|
||||
|
||||
|
4
vendor/sabre/dav/lib/DAV/ICollection.php
vendored
4
vendor/sabre/dav/lib/DAV/ICollection.php
vendored
@ -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();
|
||||
|
||||
|
2
vendor/sabre/dav/lib/DAV/IFile.php
vendored
2
vendor/sabre/dav/lib/DAV/IFile.php
vendored
@ -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);
|
||||
|
5
vendor/sabre/dav/lib/DAV/INode.php
vendored
5
vendor/sabre/dav/lib/DAV/INode.php
vendored
@ -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();
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user