upgrade to sabre32
This commit is contained in:
parent
ac4688eac0
commit
66effbfe08
@ -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;
|
||||
|
||||
|
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 ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261::getLoader();
|
||||
|
1
vendor/bin/generate_vcards
vendored
1
vendor/bin/generate_vcards
vendored
@ -1 +0,0 @@
|
||||
../sabre/vobject/bin/generate_vcards
|
241
vendor/bin/generate_vcards
vendored
Executable file
241
vendor/bin/generate_vcards
vendored
Executable file
@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
namespace Sabre\VObject;
|
||||
|
||||
// This sucks.. we have to try to find the composer autoloader. But chances
|
||||
// are, we can't find it this way. So we'll do our bestest
|
||||
$paths = [
|
||||
__DIR__ . '/../vendor/autoload.php', // In case vobject is cloned directly
|
||||
__DIR__ . '/../../../autoload.php', // In case vobject is a composer dependency.
|
||||
];
|
||||
|
||||
foreach($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('Sabre\\VObject\\Version')) {
|
||||
fwrite(STDERR, "Composer autoloader could not be properly loaded.\n");
|
||||
die(1);
|
||||
}
|
||||
|
||||
if ($argc < 2) {
|
||||
|
||||
$version = Version::VERSION;
|
||||
|
||||
$help = <<<HI
|
||||
sabre/vobject $version
|
||||
Usage:
|
||||
generate_vcards [count]
|
||||
|
||||
Options:
|
||||
count The number of random vcards to generate
|
||||
|
||||
Examples:
|
||||
generate_vcards 1000 > testdata.vcf
|
||||
|
||||
HI;
|
||||
|
||||
fwrite(STDERR, $help);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
$count = (int)$argv[1];
|
||||
if ($count < 1) {
|
||||
fwrite(STDERR, "Count must be at least 1\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
fwrite(STDERR, "sabre/vobject " . Version::VERSION . "\n");
|
||||
fwrite(STDERR, "Generating " . $count . " vcards in vCard 4.0 format\n");
|
||||
|
||||
/**
|
||||
* The following list is just some random data we compiled from various
|
||||
* sources online.
|
||||
*
|
||||
* Very little thought went into compiling this list, and certainly nothing
|
||||
* political or ethical.
|
||||
*
|
||||
* We would _love_ more additions to this to add more variation to this list.
|
||||
*
|
||||
* Send us PR's and don't be shy adding your own first and last name for fun.
|
||||
*/
|
||||
|
||||
$sets = array(
|
||||
"nl" => array(
|
||||
"country" => "Netherlands",
|
||||
"boys" => array(
|
||||
"Anno",
|
||||
"Bram",
|
||||
"Daan",
|
||||
"Evert",
|
||||
"Finn",
|
||||
"Jayden",
|
||||
"Jens",
|
||||
"Jesse",
|
||||
"Levi",
|
||||
"Lucas",
|
||||
"Luuk",
|
||||
"Milan",
|
||||
"René",
|
||||
"Sem",
|
||||
"Sibrand",
|
||||
"Willem",
|
||||
),
|
||||
"girls" => array(
|
||||
"Celia",
|
||||
"Emma",
|
||||
"Fenna",
|
||||
"Geke",
|
||||
"Inge",
|
||||
"Julia",
|
||||
"Lisa",
|
||||
"Lotte",
|
||||
"Mila",
|
||||
"Sara",
|
||||
"Sophie",
|
||||
"Tess",
|
||||
"Zoë",
|
||||
),
|
||||
"last" => array(
|
||||
"Bakker",
|
||||
"Bos",
|
||||
"De Boer",
|
||||
"De Groot",
|
||||
"De Jong",
|
||||
"De Vries",
|
||||
"Jansen",
|
||||
"Janssen",
|
||||
"Meyer",
|
||||
"Mulder",
|
||||
"Peters",
|
||||
"Smit",
|
||||
"Van Dijk",
|
||||
"Van den Berg",
|
||||
"Visser",
|
||||
"Vos",
|
||||
),
|
||||
),
|
||||
"us" => array(
|
||||
"country" => "United States",
|
||||
"boys" => array(
|
||||
"Aiden",
|
||||
"Alexander",
|
||||
"Charles",
|
||||
"David",
|
||||
"Ethan",
|
||||
"Jacob",
|
||||
"James",
|
||||
"Jayden",
|
||||
"John",
|
||||
"Joseph",
|
||||
"Liam",
|
||||
"Mason",
|
||||
"Michael",
|
||||
"Noah",
|
||||
"Richard",
|
||||
"Robert",
|
||||
"Thomas",
|
||||
"William",
|
||||
),
|
||||
"girls" => array(
|
||||
"Ava",
|
||||
"Barbara",
|
||||
"Chloe",
|
||||
"Dorothy",
|
||||
"Elizabeth",
|
||||
"Emily",
|
||||
"Emma",
|
||||
"Isabella",
|
||||
"Jennifer",
|
||||
"Lily",
|
||||
"Linda",
|
||||
"Margaret",
|
||||
"Maria",
|
||||
"Mary",
|
||||
"Mia",
|
||||
"Olivia",
|
||||
"Patricia",
|
||||
"Roxy",
|
||||
"Sophia",
|
||||
"Susan",
|
||||
"Zoe",
|
||||
),
|
||||
"last" => array(
|
||||
"Smith",
|
||||
"Johnson",
|
||||
"Williams",
|
||||
"Jones",
|
||||
"Brown",
|
||||
"Davis",
|
||||
"Miller",
|
||||
"Wilson",
|
||||
"Moore",
|
||||
"Taylor",
|
||||
"Anderson",
|
||||
"Thomas",
|
||||
"Jackson",
|
||||
"White",
|
||||
"Harris",
|
||||
"Martin",
|
||||
"Thompson",
|
||||
"Garcia",
|
||||
"Martinez",
|
||||
"Robinson",
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$current = 0;
|
||||
|
||||
$r = function($arr) {
|
||||
|
||||
return $arr[mt_rand(0,count($arr)-1)];
|
||||
|
||||
};
|
||||
|
||||
$bdayStart = strtotime('-85 years');
|
||||
$bdayEnd = strtotime('-20 years');
|
||||
|
||||
while($current < $count) {
|
||||
|
||||
$current++;
|
||||
fwrite(STDERR, "\033[100D$current/$count");
|
||||
|
||||
$country = array_rand($sets);
|
||||
$gender = mt_rand(0,1)?'girls':'boys';
|
||||
|
||||
$vcard = new Component\VCard(array(
|
||||
'VERSION' => '4.0',
|
||||
'FN' => $r($sets[$country][$gender]) . ' ' . $r($sets[$country]['last']),
|
||||
'UID' => UUIDUtil::getUUID(),
|
||||
));
|
||||
|
||||
$bdayRatio = mt_rand(0,9);
|
||||
|
||||
if($bdayRatio < 2) {
|
||||
// 20% has a birthday property with a full date
|
||||
$dt = new \DateTime('@' . mt_rand($bdayStart, $bdayEnd));
|
||||
$vcard->add('BDAY', $dt->format('Ymd'));
|
||||
|
||||
} elseif ($bdayRatio < 3) {
|
||||
// 10% we only know the month and date of
|
||||
$dt = new \DateTime('@' . mt_rand($bdayStart, $bdayEnd));
|
||||
$vcard->add('BDAY', '--' . $dt->format('md'));
|
||||
}
|
||||
if ($result = $vcard->validate()) {
|
||||
ob_start();
|
||||
echo "\nWe produced an invalid vcard somehow!\n";
|
||||
foreach($result as $message) {
|
||||
echo " " . $message['message'] . "\n";
|
||||
}
|
||||
fwrite(STDERR, ob_get_clean());
|
||||
}
|
||||
echo $vcard->serialize();
|
||||
|
||||
}
|
||||
|
||||
fwrite(STDERR,"\nDone.\n");
|
1
vendor/bin/naturalselection
vendored
1
vendor/bin/naturalselection
vendored
@ -1 +0,0 @@
|
||||
../sabre/dav/bin/naturalselection
|
140
vendor/bin/naturalselection
vendored
Executable file
140
vendor/bin/naturalselection
vendored
Executable file
@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Copyright (c) 2009-2010 Evert Pot
|
||||
# All rights reserved.
|
||||
# http://www.rooftopsolutions.nl/
|
||||
#
|
||||
# This utility is distributed along with SabreDAV
|
||||
# license: http://sabre.io/license/ Modified BSD License
|
||||
|
||||
import os
|
||||
from optparse import OptionParser
|
||||
import time
|
||||
|
||||
def getfreespace(path):
|
||||
stat = os.statvfs(path)
|
||||
return stat.f_frsize * stat.f_bavail
|
||||
|
||||
def getbytesleft(path,threshold):
|
||||
return getfreespace(path)-threshold
|
||||
|
||||
def run(cacheDir, threshold, sleep=5, simulate=False, min_erase = 0):
|
||||
|
||||
bytes = getbytesleft(cacheDir,threshold)
|
||||
if (bytes>0):
|
||||
print "Bytes to go before we hit threshold:", bytes
|
||||
else:
|
||||
print "Threshold exceeded with:", -bytes, "bytes"
|
||||
dir = os.listdir(cacheDir)
|
||||
dir2 = []
|
||||
for file in dir:
|
||||
path = cacheDir + '/' + file
|
||||
dir2.append({
|
||||
"path" : path,
|
||||
"atime": os.stat(path).st_atime,
|
||||
"size" : os.stat(path).st_size
|
||||
})
|
||||
|
||||
dir2.sort(lambda x,y: int(x["atime"]-y["atime"]))
|
||||
|
||||
filesunlinked = 0
|
||||
gainedspace = 0
|
||||
|
||||
# Left is the amount of bytes that need to be freed up
|
||||
# The default is the 'min_erase setting'
|
||||
left = min_erase
|
||||
|
||||
# If the min_erase setting is lower than the amount of bytes over
|
||||
# the threshold, we use that number instead.
|
||||
if left < -bytes :
|
||||
left = -bytes
|
||||
|
||||
print "Need to delete at least:", left;
|
||||
|
||||
for file in dir2:
|
||||
|
||||
# Only deleting files if we're not simulating
|
||||
if not simulate: os.unlink(file["path"])
|
||||
left = int(left - file["size"])
|
||||
gainedspace = gainedspace + file["size"]
|
||||
filesunlinked = filesunlinked + 1
|
||||
|
||||
if(left<0):
|
||||
break
|
||||
|
||||
print "%d files deleted (%d bytes)" % (filesunlinked, gainedspace)
|
||||
|
||||
|
||||
time.sleep(sleep)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = OptionParser(
|
||||
version="naturalselection v0.3",
|
||||
description="Cache directory manager. Deletes cache entries based on accesstime and free space thresholds.\n" +
|
||||
"This utility is distributed alongside SabreDAV.",
|
||||
usage="usage: %prog [options] cacheDirectory",
|
||||
)
|
||||
parser.add_option(
|
||||
'-s',
|
||||
dest="simulate",
|
||||
action="store_true",
|
||||
help="Don't actually make changes, but just simulate the behaviour",
|
||||
)
|
||||
parser.add_option(
|
||||
'-r','--runs',
|
||||
help="How many times to check before exiting. -1 is infinite, which is the default",
|
||||
type="int",
|
||||
dest="runs",
|
||||
default=-1
|
||||
)
|
||||
parser.add_option(
|
||||
'-n','--interval',
|
||||
help="Sleep time in seconds (default = 5)",
|
||||
type="int",
|
||||
dest="sleep",
|
||||
default=5
|
||||
)
|
||||
parser.add_option(
|
||||
'-l','--threshold',
|
||||
help="Threshold in bytes (default = 10737418240, which is 10GB)",
|
||||
type="int",
|
||||
dest="threshold",
|
||||
default=10737418240
|
||||
)
|
||||
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 number of times the cache directory will need to be scanned. " +
|
||||
"(the default is 1073741824, which is 1GB.)",
|
||||
type="int",
|
||||
dest="min_erase",
|
||||
default=1073741824
|
||||
)
|
||||
|
||||
options,args = parser.parse_args()
|
||||
if len(args)<1:
|
||||
parser.error("This utility requires at least 1 argument")
|
||||
cacheDir = args[0]
|
||||
|
||||
print "Natural Selection"
|
||||
print "Cache directory:", cacheDir
|
||||
free = getfreespace(cacheDir);
|
||||
print "Current free disk space:", free
|
||||
|
||||
runs = options.runs;
|
||||
while runs!=0 :
|
||||
run(
|
||||
cacheDir,
|
||||
sleep=options.sleep,
|
||||
simulate=options.simulate,
|
||||
threshold=options.threshold,
|
||||
min_erase=options.min_erase
|
||||
)
|
||||
if runs>0:
|
||||
runs = runs - 1
|
||||
|
||||
if __name__ == '__main__' :
|
||||
main()
|
1
vendor/bin/sabredav
vendored
1
vendor/bin/sabredav
vendored
@ -1 +0,0 @@
|
||||
../sabre/dav/bin/sabredav
|
2
vendor/bin/sabredav
vendored
Executable file
2
vendor/bin/sabredav
vendored
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
php -S 0.0.0.0:8080 `dirname $0`/sabredav.php
|
1
vendor/bin/vobject
vendored
1
vendor/bin/vobject
vendored
@ -1 +0,0 @@
|
||||
../sabre/vobject/bin/vobject
|
27
vendor/bin/vobject
vendored
Executable file
27
vendor/bin/vobject
vendored
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
namespace Sabre\VObject;
|
||||
|
||||
// This sucks.. we have to try to find the composer autoloader. But chances
|
||||
// are, we can't find it this way. So we'll do our bestest
|
||||
$paths = [
|
||||
__DIR__ . '/../vendor/autoload.php', // In case vobject is cloned directly
|
||||
__DIR__ . '/../../../autoload.php', // In case vobject is a composer dependency.
|
||||
];
|
||||
|
||||
foreach($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('Sabre\\VObject\\Version')) {
|
||||
fwrite(STDERR, "Composer autoloader could not be loaded.\n");
|
||||
die(1);
|
||||
}
|
||||
|
||||
$cli = new Cli();
|
||||
exit($cli->main($argv));
|
||||
|
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'),
|
||||
);
|
||||
|
45
vendor/composer/autoload_real.php
vendored
45
vendor/composer/autoload_real.php
vendored
@ -2,7 +2,7 @@
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
class ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
@ -19,48 +19,37 @@ class ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit85a1cefa95be2f464cf7f947cbc4c785', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInite7c34560857712ac82f3f77ff9c61261', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
|
||||
if ($useStaticLoader) {
|
||||
require_once __DIR__ . '/autoload_static.php';
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
if ($useStaticLoader) {
|
||||
$includeFiles = Composer\Autoload\ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$files;
|
||||
} else {
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
}
|
||||
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||
composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file);
|
||||
composerRequiree7c34560857712ac82f3f77ff9c61261($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
function composerRequire85a1cefa95be2f464cf7f947cbc4c785($fileIdentifier, $file)
|
||||
function composerRequiree7c34560857712ac82f3f77ff9c61261($fileIdentifier, $file)
|
||||
{
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
require $file;
|
||||
|
81
vendor/composer/autoload_static.php
vendored
81
vendor/composer/autoload_static.php
vendored
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785
|
||||
{
|
||||
public static $files = array (
|
||||
'383eaff206634a77a1be54e64e6459c7' => __DIR__ . '/..' . '/sabre/uri/lib/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',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'Sabre\\Xml\\' => 10,
|
||||
'Sabre\\VObject\\' => 14,
|
||||
'Sabre\\Uri\\' => 10,
|
||||
'Sabre\\HTTP\\' => 11,
|
||||
'Sabre\\Event\\' => 12,
|
||||
'Sabre\\DAV\\' => 10,
|
||||
'Sabre\\DAVACL\\' => 13,
|
||||
'Sabre\\CardDAV\\' => 14,
|
||||
'Sabre\\CalDAV\\' => 13,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Sabre\\Xml\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/xml/lib',
|
||||
),
|
||||
'Sabre\\VObject\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/vobject/lib',
|
||||
),
|
||||
'Sabre\\Uri\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/uri/lib',
|
||||
),
|
||||
'Sabre\\HTTP\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/http/lib',
|
||||
),
|
||||
'Sabre\\Event\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/event/lib',
|
||||
),
|
||||
'Sabre\\DAV\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/dav/lib/DAV',
|
||||
),
|
||||
'Sabre\\DAVACL\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/dav/lib/DAVACL',
|
||||
),
|
||||
'Sabre\\CardDAV\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/dav/lib/CardDAV',
|
||||
),
|
||||
'Sabre\\CalDAV\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/sabre/dav/lib/CalDAV',
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit85a1cefa95be2f464cf7f947cbc4c785::$prefixDirsPsr4;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
72
vendor/composer/installed.json
vendored
72
vendor/composer/installed.json
vendored
@ -1,4 +1,44 @@
|
||||
[
|
||||
{
|
||||
"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/uri",
|
||||
"version": "1.1.0",
|
||||
@ -170,17 +210,17 @@
|
||||
},
|
||||
{
|
||||
"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 +235,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": {
|
||||
@ -332,17 +372,17 @@
|
||||
},
|
||||
{
|
||||
"name": "sabre/dav",
|
||||
"version": "3.1.3",
|
||||
"version_normalized": "3.1.3.0",
|
||||
"version": "3.2.0-beta1",
|
||||
"version_normalized": "3.2.0.0-beta1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-dav.git",
|
||||
"reference": "8a266c7b5e140da79529414b9cde2a2d058b536b"
|
||||
"reference": "32524c79a5890056123aa64499719e7c061bfde8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-dav/zipball/8a266c7b5e140da79529414b9cde2a2d058b536b",
|
||||
"reference": "8a266c7b5e140da79529414b9cde2a2d058b536b",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-dav/zipball/32524c79a5890056123aa64499719e7c061bfde8",
|
||||
"reference": "32524c79a5890056123aa64499719e7c061bfde8",
|
||||
"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-05-21 03:49:31",
|
||||
"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
|
||||
|
2242
vendor/sabre/dav/CHANGELOG.md
vendored
2242
vendor/sabre/dav/CHANGELOG.md
vendored
File diff suppressed because it is too large
Load Diff
27
vendor/sabre/dav/LICENSE
vendored
27
vendor/sabre/dav/LICENSE
vendored
@ -1,27 +0,0 @@
|
||||
Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/).
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of SabreDAV nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
29
vendor/sabre/dav/README.md
vendored
29
vendor/sabre/dav/README.md
vendored
@ -1,29 +0,0 @@
|
||||
 SabreDAV
|
||||
======================================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
SabreDAV 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:
|
||||
|
||||
http://sabre.io/
|
||||
|
||||
Build status
|
||||
------------
|
||||
|
||||
| branch | status | minimum PHP version |
|
||||
| ------------ | ------ | ------------------- |
|
||||
| master | [](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 |
|
||||
| 1.8 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 |
|
||||
| 1.7 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 |
|
||||
| 1.6 | [](https://travis-ci.org/fruux/sabre-dav) | PHP 5.3 |
|
||||
|
||||
Made at fruux
|
||||
-------------
|
||||
|
||||
SabreDAV is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support.
|
2
vendor/sabre/dav/bin/build.php
vendored
2
vendor/sabre/dav/bin/build.php
vendored
@ -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);
|
||||
|
52
vendor/sabre/dav/bin/migrateto17.php
vendored
52
vendor/sabre/dav/bin/migrateto17.php
vendored
@ -3,7 +3,7 @@
|
||||
|
||||
echo "SabreDAV migrate script for version 1.7\n";
|
||||
|
||||
if ($argc < 2) {
|
||||
if ($argc<2) {
|
||||
|
||||
echo <<<HELLO
|
||||
|
||||
@ -35,12 +35,12 @@ HELLO;
|
||||
|
||||
// There's a bunch of places where the autoloader could be, so we'll try all of
|
||||
// them.
|
||||
$paths = [
|
||||
$paths = array(
|
||||
__DIR__ . '/../vendor/autoload.php',
|
||||
__DIR__ . '/../../../autoload.php',
|
||||
];
|
||||
);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
foreach($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
@ -48,8 +48,8 @@ foreach ($paths as $path) {
|
||||
}
|
||||
|
||||
$dsn = $argv[1];
|
||||
$user = isset($argv[2]) ? $argv[2] : null;
|
||||
$pass = isset($argv[3]) ? $argv[3] : null;
|
||||
$user = isset($argv[2])?$argv[2]:null;
|
||||
$pass = isset($argv[3])?$argv[3]:null;
|
||||
|
||||
echo "Connecting to database: " . $dsn . "\n";
|
||||
|
||||
@ -67,32 +67,32 @@ if (!$row) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$requiredFields = [
|
||||
$requiredFields = array(
|
||||
'id',
|
||||
'calendardata',
|
||||
'uri',
|
||||
'calendarid',
|
||||
'lastmodified',
|
||||
];
|
||||
);
|
||||
|
||||
foreach ($requiredFields as $requiredField) {
|
||||
if (!array_key_exists($requiredField, $row)) {
|
||||
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 = [
|
||||
$fields17 = array(
|
||||
'etag',
|
||||
'size',
|
||||
'componenttype',
|
||||
'firstoccurence',
|
||||
'lastoccurence',
|
||||
];
|
||||
);
|
||||
|
||||
$found = 0;
|
||||
foreach ($fields17 as $field) {
|
||||
foreach($fields17 as $field) {
|
||||
if (array_key_exists($field, $row)) {
|
||||
$found++;
|
||||
}
|
||||
@ -102,7 +102,7 @@ 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)) {
|
||||
switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
|
||||
case 'mysql' :
|
||||
|
||||
@ -150,7 +150,7 @@ $stmt = $pdo->prepare('UPDATE calendarobjects SET etag = ?, size = ?, componentt
|
||||
echo "Total records found: " . $result->rowCount() . "\n";
|
||||
$done = 0;
|
||||
$total = $result->rowCount();
|
||||
while ($row = $result->fetch()) {
|
||||
while($row = $result->fetch()) {
|
||||
|
||||
try {
|
||||
$newData = getDenormalizedData($row['calendardata']);
|
||||
@ -161,14 +161,14 @@ while ($row = $result->fetch()) {
|
||||
echo "This record is ignored, you should inspect it to see if there's anything wrong.\n===\n";
|
||||
continue;
|
||||
}
|
||||
$stmt->execute([
|
||||
$stmt->execute(array(
|
||||
$newData['etag'],
|
||||
$newData['size'],
|
||||
$newData['componentType'],
|
||||
$newData['firstOccurence'],
|
||||
$newData['lastOccurence'],
|
||||
$row['id'],
|
||||
]);
|
||||
));
|
||||
$done++;
|
||||
|
||||
if ($done % 500 === 0) {
|
||||
@ -188,7 +188,7 @@ if (array_key_exists('transparent', $row)) {
|
||||
|
||||
echo "Adding the 'transparent' field to the calendars table\n";
|
||||
|
||||
switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
|
||||
case 'mysql' :
|
||||
$pdo->exec("ALTER TABLE calendars ADD transparent TINYINT(1) NOT NULL DEFAULT '0'");
|
||||
@ -229,8 +229,8 @@ function getDenormalizedData($calendarData) {
|
||||
$component = null;
|
||||
$firstOccurence = null;
|
||||
$lastOccurence = null;
|
||||
foreach ($vObject->getComponents() as $component) {
|
||||
if ($component->name !== 'VTIMEZONE') {
|
||||
foreach($vObject->getComponents() as $component) {
|
||||
if ($component->name!=='VTIMEZONE') {
|
||||
$componentType = $component->name;
|
||||
break;
|
||||
}
|
||||
@ -262,7 +262,7 @@ function getDenormalizedData($calendarData) {
|
||||
$lastOccurence = $maxDate->getTimeStamp();
|
||||
} else {
|
||||
$end = $it->getDtEnd();
|
||||
while ($it->valid() && $end < $maxDate) {
|
||||
while($it->valid() && $end < $maxDate) {
|
||||
$end = $it->getDtEnd();
|
||||
$it->next();
|
||||
|
||||
@ -273,12 +273,12 @@ function getDenormalizedData($calendarData) {
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'etag' => md5($calendarData),
|
||||
'size' => strlen($calendarData),
|
||||
'componentType' => $componentType,
|
||||
return array(
|
||||
'etag' => md5($calendarData),
|
||||
'size' => strlen($calendarData),
|
||||
'componentType' => $componentType,
|
||||
'firstOccurence' => $firstOccurence,
|
||||
'lastOccurence' => $lastOccurence,
|
||||
];
|
||||
);
|
||||
|
||||
}
|
||||
|
4
vendor/sabre/dav/bin/migrateto21.php
vendored
4
vendor/sabre/dav/bin/migrateto21.php
vendored
@ -169,10 +169,6 @@ switch ($driver) {
|
||||
)
|
||||
');
|
||||
break;
|
||||
$pdo->exec('
|
||||
CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri);
|
||||
');
|
||||
break;
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
||||
|
268
vendor/sabre/dav/bin/migrateto32.php
vendored
Executable file
268
vendor/sabre/dav/bin/migrateto32.php
vendored
Executable 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(20)
|
||||
) 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",
|
||||
|
@ -6,7 +6,7 @@ CREATE TABLE addressbooks (
|
||||
description TEXT,
|
||||
synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1',
|
||||
UNIQUE(principaluri(100), uri(100))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE cards (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
@ -16,7 +16,7 @@ CREATE TABLE cards (
|
||||
lastmodified INT(11) UNSIGNED,
|
||||
etag VARBINARY(32),
|
||||
size INT(11) UNSIGNED NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE addressbookchanges (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
@ -25,4 +25,4 @@ CREATE TABLE addressbookchanges (
|
||||
addressbookid INT(11) UNSIGNED NOT NULL,
|
||||
operation TINYINT(1) NOT NULL,
|
||||
INDEX addressbookid_synctoken (addressbookid, synctoken)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
@ -10,22 +10,34 @@ CREATE TABLE calendarobjects (
|
||||
firstoccurence INT(11) UNSIGNED,
|
||||
lastoccurence INT(11) UNSIGNED,
|
||||
uid VARBINARY(200),
|
||||
UNIQUE(calendarid, uri)
|
||||
UNIQUE(calendarid, uri),
|
||||
INDEX calendarid_time (calendarid, firstoccurence)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
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=utf8mb4;
|
||||
|
||||
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),
|
||||
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)
|
||||
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;
|
||||
|
||||
CREATE TABLE calendarchanges (
|
||||
|
@ -1,27 +1,6 @@
|
||||
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,
|
||||
calendardata BYTEA,
|
||||
uri VARCHAR(200),
|
||||
calendarid INTEGER NOT NULL,
|
||||
lastmodified INTEGER,
|
||||
@ -39,9 +18,46 @@ ALTER TABLE ONLY calendarobjects
|
||||
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 calendars (
|
||||
id SERIAL NOT NULL,
|
||||
synctoken INTEGER NOT NULL DEFAULT 1,
|
||||
components VARCHAR(21)
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendars
|
||||
ADD CONSTRAINT calendars_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
CREATE TABLE calendarinstances (
|
||||
id SERIAL NOT NULL,
|
||||
calendarid INTEGER NOT NULL,
|
||||
principaluri VARCHAR(100),
|
||||
access SMALLINT NOT NULL DEFAULT '1', -- '1 = owner, 2 = read, 3 = readwrite'
|
||||
displayname VARCHAR(100),
|
||||
uri VARCHAR(200),
|
||||
description TEXT,
|
||||
calendarorder INTEGER NOT NULL DEFAULT 0,
|
||||
calendarcolor VARCHAR(10),
|
||||
timezone TEXT,
|
||||
transparent SMALLINT NOT NULL DEFAULT '0',
|
||||
share_href VARCHAR(100),
|
||||
share_displayname VARCHAR(100),
|
||||
share_invitestatus SMALLINT NOT NULL DEFAULT '2' -- '1 = noresponse, 2 = accepted, 3 = declined, 4 = invalid'
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendarinstances
|
||||
ADD CONSTRAINT calendarinstances_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX calendarinstances_principaluri_uri
|
||||
ON calendarinstances USING btree (principaluri, uri);
|
||||
|
||||
|
||||
CREATE UNIQUE INDEX calendarinstances_principaluri_calendarid
|
||||
ON calendarinstances USING btree (principaluri, calendarid);
|
||||
|
||||
CREATE UNIQUE INDEX calendarinstances_principaluri_share_href
|
||||
ON calendarinstances USING btree (principaluri, share_href);
|
||||
|
||||
CREATE TABLE calendarsubscriptions (
|
||||
id SERIAL NOT NULL,
|
||||
@ -78,10 +94,6 @@ ALTER TABLE ONLY calendarchanges
|
||||
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),
|
||||
|
@ -23,14 +23,6 @@ ALTER TABLE ONLY groupmembers
|
||||
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),
|
||||
|
@ -14,16 +14,28 @@ CREATE TABLE calendarobjects (
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id integer primary key asc NOT NULL,
|
||||
principaluri text NOT NULL,
|
||||
synctoken integer DEFAULT 1 NOT NULL,
|
||||
components text NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE calendarinstances (
|
||||
id integer primary key asc NOT NULL,
|
||||
calendarid integer NOT NULL,
|
||||
principaluri text NULL,
|
||||
access integer COMMENT '1 = owner, 2 = read, 3 = readwrite' NOT NULL DEFAULT '1',
|
||||
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
|
||||
transparent bool,
|
||||
share_href text,
|
||||
share_displayname text,
|
||||
share_invitestatus integer DEFAULT '2',
|
||||
UNIQUE (principaluri, uri),
|
||||
UNIQUE (calendarid, principaluri),
|
||||
UNIQUE (calendarid, share_href)
|
||||
);
|
||||
|
||||
CREATE TABLE calendarchanges (
|
||||
|
@ -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 \Exception('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'];
|
||||
|
@ -5,7 +5,7 @@ namespace Sabre\CalDAV;
|
||||
/**
|
||||
* This interface represents a Calendar that can be shared with other users.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
|
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,
|
||||
],
|
||||
|
@ -6,7 +6,7 @@ namespace Sabre\CalDAV;
|
||||
* This object represents a CalDAV calendar that can be shared with other
|
||||
* users.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
|
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
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)
|
||||
];
|
||||
|
||||
}
|
||||
|
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]);
|
||||
}
|
||||
|
39
vendor/sabre/dav/lib/DAV/Server.php
vendored
39
vendor/sabre/dav/lib/DAV/Server.php
vendored
@ -8,6 +8,10 @@ use Sabre\HTTP\RequestInterface;
|
||||
use Sabre\HTTP\ResponseInterface;
|
||||
use Sabre\HTTP\URLUtil;
|
||||
use Sabre\Uri;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
/**
|
||||
* Main DAV server class
|
||||
@ -16,7 +20,9 @@ use Sabre\Uri;
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Server extends EventEmitter {
|
||||
class Server extends EventEmitter implements LoggerAwareInterface {
|
||||
|
||||
use LoggerAwareTrait;
|
||||
|
||||
/**
|
||||
* Infinity is used for some request supporting the HTTP Depth header and indicates that the operation should traverse the entire tree
|
||||
@ -430,6 +436,20 @@ class Server extends EventEmitter {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PSR-3 logger objcet.
|
||||
*
|
||||
* @return LoggerInterface
|
||||
*/
|
||||
function getLogger() {
|
||||
|
||||
if (!$this->logger) {
|
||||
$this->logger = new NullLogger();
|
||||
}
|
||||
return $this->logger;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a http request, and execute a method based on its name
|
||||
*
|
||||
@ -1177,9 +1197,20 @@ class Server extends EventEmitter {
|
||||
|
||||
if (!$success) {
|
||||
$result = $mkCol->getResult();
|
||||
// generateMkCol needs the href key to exist.
|
||||
$result['href'] = $uri;
|
||||
return $result;
|
||||
|
||||
$formattedResult = [
|
||||
'href' => $uri,
|
||||
];
|
||||
|
||||
foreach ($result as $propertyName => $status) {
|
||||
|
||||
if (!isset($formattedResult[$status])) {
|
||||
$formattedResult[$status] = [];
|
||||
}
|
||||
$formattedResult[$status][$propertyName] = null;
|
||||
|
||||
}
|
||||
return $formattedResult;
|
||||
}
|
||||
|
||||
$this->tree->markDirty($parentUri);
|
||||
|
69
vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php
vendored
Normal file
69
vendor/sabre/dav/lib/DAV/Sharing/ISharedNode.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Sharing;
|
||||
|
||||
use Sabre\DAV\INode;
|
||||
|
||||
/**
|
||||
* This interface represents a resource that has sharing capabilities, either
|
||||
* because it's possible for an owner to share the resource, or because this is
|
||||
* an instance of a shared resource.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH. (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
interface ISharedNode extends INode {
|
||||
|
||||
/**
|
||||
* Returns the 'access level' for the instance of this shared resource.
|
||||
*
|
||||
* The value should be one of the Sabre\DAV\Sharing\Plugin::ACCESS_
|
||||
* constants.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function getShareAccess();
|
||||
|
||||
/**
|
||||
* This function must return a URI that uniquely identifies the shared
|
||||
* resource. This URI should be identical across instances, and is
|
||||
* also used in several other XML bodies to connect invites to
|
||||
* resources.
|
||||
*
|
||||
* This may simply be a relative reference to the original shared instance,
|
||||
* but it could also be a urn. As long as it's a valid URI and unique.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getShareResourceUri();
|
||||
|
||||
/**
|
||||
* Updates the list of sharees.
|
||||
*
|
||||
* Every item must be a Sharee object.
|
||||
*
|
||||
* @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
|
||||
* @return void
|
||||
*/
|
||||
function updateInvites(array $sharees);
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this resource is shared with.
|
||||
*
|
||||
* Every item in the returned array must be a Sharee object with
|
||||
* at least the following properties set:
|
||||
*
|
||||
* * $href
|
||||
* * $shareAccess
|
||||
* * $inviteStatus
|
||||
*
|
||||
* and optionally:
|
||||
*
|
||||
* * $properties
|
||||
*
|
||||
* @return \Sabre\DAV\Xml\Element\Sharee[]
|
||||
*/
|
||||
function getInvites();
|
||||
|
||||
}
|
342
vendor/sabre/dav/lib/DAV/Sharing/Plugin.php
vendored
Normal file
342
vendor/sabre/dav/lib/DAV/Sharing/Plugin.php
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Sharing;
|
||||
|
||||
use Sabre\DAV\Exception\BadRequest;
|
||||
use Sabre\DAV\Exception\Forbidden;
|
||||
use Sabre\DAV\INode;
|
||||
use Sabre\DAV\PropFind;
|
||||
use Sabre\DAV\Server;
|
||||
use Sabre\DAV\ServerPlugin;
|
||||
use Sabre\DAV\Xml\Property;
|
||||
use Sabre\DAV\Xml\Element\Sharee;
|
||||
use Sabre\HTTP\RequestInterface;
|
||||
use Sabre\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* This plugin implements HTTP requests and properties related to:
|
||||
*
|
||||
* draft-pot-webdav-resource-sharing
|
||||
*
|
||||
* This specification allows people to share webdav resources with others.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2015 fruux GmbH. (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Plugin extends ServerPlugin {
|
||||
|
||||
const ACCESS_NOTSHARED = 0;
|
||||
const ACCESS_SHAREDOWNER = 1;
|
||||
const ACCESS_READ = 2;
|
||||
const ACCESS_READWRITE = 3;
|
||||
const ACCESS_NOACCESS = 4;
|
||||
|
||||
const INVITE_NORESPONSE = 1;
|
||||
const INVITE_ACCEPTED = 2;
|
||||
const INVITE_DECLINED = 3;
|
||||
const INVITE_INVALID = 4;
|
||||
|
||||
/**
|
||||
* Reference to SabreDAV server object.
|
||||
*
|
||||
* @var Sabre\DAV\Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* This method should return a list of server-features.
|
||||
*
|
||||
* This is for example 'versioning' and is added to the DAV: header
|
||||
* in an OPTIONS response.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getFeatures() {
|
||||
|
||||
return ['resource-sharing'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a plugin name.
|
||||
*
|
||||
* Using this name other plugins will be able to access other plugins
|
||||
* using \Sabre\DAV\Server::getPlugin
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getPluginName() {
|
||||
|
||||
return 'sharing';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes the plugin.
|
||||
*
|
||||
* This function is called by Sabre\DAV\Server, after
|
||||
* addPlugin is called.
|
||||
*
|
||||
* This method should set up the required event subscriptions.
|
||||
*
|
||||
* @param Server $server
|
||||
* @return void
|
||||
*/
|
||||
function initialize(Server $server) {
|
||||
|
||||
$this->server = $server;
|
||||
|
||||
$server->xml->elementMap['{DAV:}share-resource'] = 'Sabre\\DAV\\Xml\\Request\\ShareResource';
|
||||
|
||||
array_push(
|
||||
$server->protectedProperties,
|
||||
'{DAV:}share-mode'
|
||||
);
|
||||
|
||||
$server->on('method:POST', [$this, 'httpPost']);
|
||||
$server->on('propFind', [$this, 'propFind']);
|
||||
$server->on('getSupportedPrivilegeSet', [$this, 'getSupportedPrivilegeSet']);
|
||||
$server->on('onHTMLActionsPanel', [$this, 'htmlActionsPanel']);
|
||||
$server->on('onBrowserPostAction', [$this, 'browserPostAction']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of sharees on a shared resource.
|
||||
*
|
||||
* The sharees array is a list of people that are to be added modified
|
||||
* or removed in the list of shares.
|
||||
*
|
||||
* @param string $path
|
||||
* @param Sharee[] $sharees
|
||||
* @return void
|
||||
*/
|
||||
function shareResource($path, array $sharees) {
|
||||
|
||||
$node = $this->server->tree->getNodeForPath($path);
|
||||
|
||||
if (!$node instanceof ISharedNode) {
|
||||
|
||||
throw new Forbidden('Sharing is not allowed on this node');
|
||||
|
||||
}
|
||||
|
||||
// Getting ACL info
|
||||
$acl = $this->server->getPlugin('acl');
|
||||
|
||||
// If there's no ACL support, we allow everything
|
||||
if ($acl) {
|
||||
$acl->checkPrivileges($path, '{DAV:}share');
|
||||
}
|
||||
|
||||
foreach ($sharees as $sharee) {
|
||||
// We're going to attempt to get a local principal uri for a share
|
||||
// href by emitting the getPrincipalByUri event.
|
||||
$principal = null;
|
||||
$this->server->emit('getPrincipalByUri', [$sharee->href, &$principal]);
|
||||
$sharee->principal = $principal;
|
||||
}
|
||||
$node->updateInvites($sharees);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is triggered when properties are requested for nodes.
|
||||
*
|
||||
* This allows us to inject any sharings-specific properties.
|
||||
*
|
||||
* @param PropFind $propFind
|
||||
* @param INode $node
|
||||
* @return void
|
||||
*/
|
||||
function propFind(PropFind $propFind, INode $node) {
|
||||
|
||||
if ($node instanceof ISharedNode) {
|
||||
|
||||
$propFind->handle('{DAV:}share-access', function() use ($node) {
|
||||
|
||||
return new Property\ShareAccess($node->getShareAccess());
|
||||
|
||||
});
|
||||
$propFind->handle('{DAV:}invite', function() use ($node) {
|
||||
|
||||
return new Property\Invite($node->getInvites());
|
||||
|
||||
});
|
||||
$propFind->handle('{DAV:}share-resource-uri', function() use ($node) {
|
||||
|
||||
return new Property\Href($node->getShareResourceUri());
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* We intercept this to handle POST requests on shared resources
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @return null|bool
|
||||
*/
|
||||
function httpPost(RequestInterface $request, ResponseInterface $response) {
|
||||
|
||||
$path = $request->getPath();
|
||||
$contentType = $request->getHeader('Content-Type');
|
||||
|
||||
// We're only interested in the davsharing content type.
|
||||
if (strpos($contentType, 'application/davsharing+xml') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = $this->server->xml->parse(
|
||||
$request->getBody(),
|
||||
$request->getUrl(),
|
||||
$documentType
|
||||
);
|
||||
|
||||
switch ($documentType) {
|
||||
|
||||
case '{DAV:}share-resource':
|
||||
|
||||
$this->shareResource($path, $message->sharees);
|
||||
$response->setStatus(200);
|
||||
// Adding this because sending a response body may cause issues,
|
||||
// and I wanted some type of indicator the response was handled.
|
||||
$response->setHeader('X-Sabre-Status', 'everything-went-well');
|
||||
|
||||
// Breaking the event chain
|
||||
return false;
|
||||
|
||||
default :
|
||||
throw new BadRequest('Unexpected document type: ' . $documentType . ' for this Content-Type');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is triggered whenever a subsystem reqeuests the privileges
|
||||
* hat are supported on a particular node.
|
||||
*
|
||||
* We need to add a number of privileges for scheduling purposes.
|
||||
*
|
||||
* @param INode $node
|
||||
* @param array $supportedPrivilegeSet
|
||||
*/
|
||||
function getSupportedPrivilegeSet(INode $node, array &$supportedPrivilegeSet) {
|
||||
|
||||
if ($node instanceof ISharedNode) {
|
||||
$supportedPrivilegeSet['{DAV:}share'] = [
|
||||
'abstract' => false,
|
||||
'aggregates' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bunch of meta-data about the plugin.
|
||||
*
|
||||
* Providing this information is optional, and is mainly displayed by the
|
||||
* Browser plugin.
|
||||
*
|
||||
* The description key in the returned array may contain html and will not
|
||||
* be sanitized.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getPluginInfo() {
|
||||
|
||||
return [
|
||||
'name' => $this->getPluginName(),
|
||||
'description' => 'This plugin implements WebDAV resource sharing',
|
||||
'link' => 'https://github.com/evert/webdav-sharing'
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to generate HTML output for the
|
||||
* DAV\Browser\Plugin.
|
||||
*
|
||||
* @param INode $node
|
||||
* @param string $output
|
||||
* @param string $path
|
||||
* @return bool|null
|
||||
*/
|
||||
function htmlActionsPanel(INode $node, &$output, $path) {
|
||||
|
||||
if (!$node instanceof ISharedNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
$aclPlugin = $this->server->getPlugin('acl');
|
||||
if ($aclPlugin) {
|
||||
if (!$aclPlugin->checkPrivileges($path, '{DAV:}share', \Sabre\DAVACL\Plugin::R_PARENT, false)) {
|
||||
// Sharing is not permitted, we will not draw this interface.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$output .= '<tr><td colspan="2"><form method="post" action="">
|
||||
<h3>Share this resource</h3>
|
||||
<input type="hidden" name="sabreAction" value="share" />
|
||||
<label>Share with (uri):</label> <input type="text" name="href" placeholder="mailto:user@example.org"/><br />
|
||||
<label>Access</label>
|
||||
<select name="access">
|
||||
<option value="readwrite">Read-write</option>
|
||||
<option value="read">Read-only</option>
|
||||
<option value="no-access">Revoke access</option>
|
||||
</select><br />
|
||||
<input type="submit" value="share" />
|
||||
</form>
|
||||
</td></tr>';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is triggered for POST actions generated by the browser
|
||||
* plugin.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $action
|
||||
* @param array $postVars
|
||||
*/
|
||||
function browserPostAction($path, $action, $postVars) {
|
||||
|
||||
if ($action !== 'share') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (empty($postVars['href'])) {
|
||||
throw new BadRequest('The "href" POST parameter is required');
|
||||
}
|
||||
if (empty($postVars['access'])) {
|
||||
throw new BadRequest('The "access" POST parameter is required');
|
||||
}
|
||||
|
||||
$accessMap = [
|
||||
'readwrite' => self::ACCESS_READWRITE,
|
||||
'read' => self::ACCESS_READ,
|
||||
'no-access' => self::ACCESS_NOACCESS,
|
||||
];
|
||||
|
||||
if (!isset($accessMap[$postVars['access']])) {
|
||||
throw new BadRequest('The "access" POST must be readwrite, read or no-access');
|
||||
}
|
||||
$sharee = new Sharee([
|
||||
'href' => $postVars['href'],
|
||||
'access' => $accessMap[$postVars['access']],
|
||||
]);
|
||||
|
||||
$this->shareResource(
|
||||
$path,
|
||||
[$sharee]
|
||||
);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
2
vendor/sabre/dav/lib/DAV/Tree.php
vendored
2
vendor/sabre/dav/lib/DAV/Tree.php
vendored
@ -229,7 +229,7 @@ class Tree {
|
||||
// flushing the entire cache
|
||||
$path = trim($path, '/');
|
||||
foreach ($this->cache as $nodePath => $node) {
|
||||
if ($nodePath == $path || strpos($nodePath, $path . '/') === 0)
|
||||
if ($path === '' || $nodePath == $path || strpos($nodePath, $path . '/') === 0)
|
||||
unset($this->cache[$nodePath]);
|
||||
|
||||
}
|
||||
|
2
vendor/sabre/dav/lib/DAV/Version.php
vendored
2
vendor/sabre/dav/lib/DAV/Version.php
vendored
@ -14,6 +14,6 @@ class Version {
|
||||
/**
|
||||
* Full version number
|
||||
*/
|
||||
const VERSION = '3.1.3';
|
||||
const VERSION = '3.2.0-beta1';
|
||||
|
||||
}
|
||||
|
199
vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php
vendored
Normal file
199
vendor/sabre/dav/lib/DAV/Xml/Element/Sharee.php
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Xml\Element;
|
||||
|
||||
use Sabre\DAV\Exception\BadRequest;
|
||||
use Sabre\DAV\Sharing\Plugin;
|
||||
use Sabre\DAV\Xml\Property\Href;
|
||||
use Sabre\DAV\Xml\Property\ShareAccess;
|
||||
use Sabre\Xml\Deserializer;
|
||||
use Sabre\Xml\Element;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\Writer;
|
||||
|
||||
/**
|
||||
* This class represents the {DAV:}sharee element.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH. (https://fruux.com/)
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Sharee implements Element {
|
||||
|
||||
/**
|
||||
* A URL. Usually a mailto: address, could also be a principal url.
|
||||
* This uniquely identifies the sharee.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $href;
|
||||
|
||||
/**
|
||||
* A local principal path. The server will do its best to locate the
|
||||
* principal uri based on the given uri. If we could find a local matching
|
||||
* principal uri, this property will contain the value.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $principal;
|
||||
|
||||
/**
|
||||
* A list of WebDAV properties that describe the sharee. This might for
|
||||
* example contain a {DAV:}displayname with the real name of the user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $properties = [];
|
||||
|
||||
/**
|
||||
* Share access level. One of the Sabre\DAV\Sharing\Plugin::ACCESS
|
||||
* constants.
|
||||
*
|
||||
* Can be one of:
|
||||
*
|
||||
* ACCESS_READ
|
||||
* ACCESS_READWRITE
|
||||
* ACCESS_SHAREDOWNER
|
||||
* ACCESS_NOACCESS
|
||||
*
|
||||
* depending on context.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $access;
|
||||
|
||||
/**
|
||||
* When a sharee is originally invited to a share, the sharer may add
|
||||
* a comment. This will be placed in this property.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $comment;
|
||||
|
||||
/**
|
||||
* The status of the invite, should be one of the
|
||||
* Sabre\DAV\Sharing\Plugin::INVITE constants.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $inviteStatus;
|
||||
|
||||
/**
|
||||
* Creates the object
|
||||
*
|
||||
* $properties will be used to populate all internal properties.
|
||||
*
|
||||
* @param array $properties
|
||||
*/
|
||||
function __construct(array $properties = []) {
|
||||
|
||||
foreach ($properties as $k => $v) {
|
||||
|
||||
if (property_exists($this, $k)) {
|
||||
$this->$k = $v;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Unknown property: ' . $k);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The xmlSerialize method is called during xml writing.
|
||||
*
|
||||
* Use the $writer argument to write its own xml serialization.
|
||||
*
|
||||
* An important note: do _not_ create a parent element. Any element
|
||||
* implementing XmlSerializble should only ever write what's considered
|
||||
* its 'inner xml'.
|
||||
*
|
||||
* The parent of the current element is responsible for writing a
|
||||
* containing element.
|
||||
*
|
||||
* This allows serializers to be re-used for different element names.
|
||||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*
|
||||
* @param Writer $writer
|
||||
* @return void
|
||||
*/
|
||||
function xmlSerialize(Writer $writer) {
|
||||
|
||||
|
||||
$writer->write([
|
||||
new Href($this->href),
|
||||
'{DAV:}prop' => $this->properties,
|
||||
'{DAV:}share-access' => new ShareAccess($this->access),
|
||||
]);
|
||||
switch ($this->inviteStatus) {
|
||||
case Plugin::INVITE_NORESPONSE :
|
||||
$writer->writeElement('{DAV:}invite-noresponse');
|
||||
break;
|
||||
case Plugin::INVITE_ACCEPTED :
|
||||
$writer->writeElement('{DAV:}invite-accepted');
|
||||
break;
|
||||
case Plugin::INVITE_DECLINED :
|
||||
$writer->writeElement('{DAV:}invite-declined');
|
||||
break;
|
||||
case Plugin::INVITE_INVALID :
|
||||
$writer->writeElement('{DAV:}invite-invalid');
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserialize method is called during xml parsing.
|
||||
*
|
||||
* This method is called statictly, this is because in theory this method
|
||||
* may be used as a type of constructor, or factory method.
|
||||
*
|
||||
* Often you want to return an instance of the current class, but you are
|
||||
* free to return other data as well.
|
||||
*
|
||||
* You are responsible for advancing the reader to the next element. Not
|
||||
* doing anything will result in a never-ending loop.
|
||||
*
|
||||
* If you just want to skip parsing for this element altogether, you can
|
||||
* just call $reader->next();
|
||||
*
|
||||
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @param Reader $reader
|
||||
* @return mixed
|
||||
*/
|
||||
static function xmlDeserialize(Reader $reader) {
|
||||
|
||||
// Temporarily override configuration
|
||||
$reader->pushContext();
|
||||
$reader->elementMap['{DAV:}share-access'] = 'Sabre\DAV\Xml\Property\ShareAccess';
|
||||
$reader->elementMap['{DAV:}prop'] = 'Sabre\Xml\Deserializer\keyValue';
|
||||
|
||||
$elems = Deserializer\keyValue($reader, 'DAV:');
|
||||
|
||||
// Restore previous configuration
|
||||
$reader->popContext();
|
||||
|
||||
$sharee = new self();
|
||||
if (!isset($elems['href'])) {
|
||||
throw new BadRequest('Every {DAV:}sharee must have a {DAV:}href child-element');
|
||||
}
|
||||
$sharee->href = $elems['href'];
|
||||
|
||||
if (isset($elems['prop'])) {
|
||||
$sharee->properties = $elems['prop'];
|
||||
}
|
||||
if (isset($elems['comment'])) {
|
||||
$sharee->comment = $elems['comment'];
|
||||
}
|
||||
if (!isset($elems['share-access'])) {
|
||||
throw new BadRequest('Every {DAV:}sharee must have a {DAV:}share-access child element');
|
||||
}
|
||||
$sharee->access = $elems['share-access']->getValue();
|
||||
return $sharee;
|
||||
|
||||
}
|
||||
|
||||
}
|
17
vendor/sabre/dav/lib/DAV/Xml/Property/Href.php
vendored
17
vendor/sabre/dav/lib/DAV/Xml/Property/Href.php
vendored
@ -7,6 +7,7 @@ use Sabre\DAV\Browser\HtmlOutputHelper;
|
||||
use Sabre\Xml\Element;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\Writer;
|
||||
use Sabre\Uri;
|
||||
|
||||
/**
|
||||
* Href property
|
||||
@ -31,13 +32,6 @@ class Href implements Element, HtmlOutput {
|
||||
*/
|
||||
protected $hrefs;
|
||||
|
||||
/**
|
||||
* Automatically prefix the url with the server base directory
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoPrefix = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -47,16 +41,13 @@ class Href implements Element, HtmlOutput {
|
||||
* and not relative to the servers base uri.
|
||||
*
|
||||
* @param string|string[] $href
|
||||
* @param bool $autoPrefix
|
||||
*/
|
||||
function __construct($hrefs, $autoPrefix = true) {
|
||||
function __construct($hrefs) {
|
||||
|
||||
if (is_string($hrefs)) {
|
||||
$hrefs = [$hrefs];
|
||||
}
|
||||
$this->hrefs = $hrefs;
|
||||
$this->autoPrefix = $autoPrefix;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -104,9 +95,7 @@ class Href implements Element, HtmlOutput {
|
||||
function xmlSerialize(Writer $writer) {
|
||||
|
||||
foreach ($this->getHrefs() as $href) {
|
||||
if ($this->autoPrefix) {
|
||||
$href = $writer->contextUri . \Sabre\HTTP\encodePath($href);
|
||||
}
|
||||
$href = Uri\resolve($writer->contextUri, $href);
|
||||
$writer->writeElement('{DAV:}href', $href);
|
||||
}
|
||||
|
||||
|
70
vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php
vendored
Normal file
70
vendor/sabre/dav/lib/DAV/Xml/Property/Invite.php
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Xml\Property;
|
||||
|
||||
use Sabre\DAV\Sharing\Sharee;
|
||||
use Sabre\Xml\XmlSerializable;
|
||||
use Sabre\Xml\Writer;
|
||||
|
||||
/**
|
||||
* This class represents the {DAV:}invite property.
|
||||
*
|
||||
* This property is defined here:
|
||||
* https://tools.ietf.org/html/draft-pot-webdav-resource-sharing-03#section-4.4.2
|
||||
*
|
||||
* This property is used by clients to determine who currently has access to
|
||||
* a shared resource, what their access level is and what their invite status
|
||||
* is.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class Invite implements XmlSerializable {
|
||||
|
||||
/**
|
||||
* A list of sharees
|
||||
*
|
||||
* @var Sharee[]
|
||||
*/
|
||||
public $sharees = [];
|
||||
|
||||
/**
|
||||
* Creates the property.
|
||||
*
|
||||
* @param Sharee[] $sharees
|
||||
*/
|
||||
function __construct(array $sharees) {
|
||||
|
||||
$this->sharees = $sharees;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The xmlSerialize method is called during xml writing.
|
||||
*
|
||||
* Use the $writer argument to write its own xml serialization.
|
||||
*
|
||||
* An important note: do _not_ create a parent element. Any element
|
||||
* implementing XmlSerializble should only ever write what's considered
|
||||
* its 'inner xml'.
|
||||
*
|
||||
* The parent of the current element is responsible for writing a
|
||||
* containing element.
|
||||
*
|
||||
* This allows serializers to be re-used for different element names.
|
||||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*
|
||||
* @param Writer $writer
|
||||
* @return void
|
||||
*/
|
||||
function xmlSerialize(Writer $writer) {
|
||||
|
||||
foreach ($this->sharees as $sharee) {
|
||||
$writer->writeElement('{DAV:}sharee', $sharee);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
48
vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php
vendored
Normal file
48
vendor/sabre/dav/lib/DAV/Xml/Property/LocalHref.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Xml\Property;
|
||||
|
||||
use Sabre\HTTP;
|
||||
|
||||
/**
|
||||
* LocalHref property
|
||||
*
|
||||
* Like the Href property, this element represents {DAV:}href. The difference
|
||||
* is that this is used stricly for paths on the server. The LocalHref property
|
||||
* will prepare the path so it's a valid URI.
|
||||
*
|
||||
* These two objects behave identically:
|
||||
* new LocalHref($path)
|
||||
* new Href(\Sabre\HTTP\encodePath($path))
|
||||
*
|
||||
* LocalPath basically ensures that your spaces are %20, and everything that
|
||||
* needs to be is uri encoded.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class LocalHref extends Href {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* You must either pass a string for a single href, or an array of hrefs.
|
||||
*
|
||||
* If auto-prefix is set to false, the hrefs will be treated as absolute
|
||||
* and not relative to the servers base uri.
|
||||
*
|
||||
* @param string|string[] $href
|
||||
*/
|
||||
function __construct($hrefs) {
|
||||
|
||||
parent::__construct(array_map(
|
||||
function($href) {
|
||||
return \Sabre\HTTP\encodePath($href);
|
||||
},
|
||||
(array)$hrefs
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
}
|
143
vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php
vendored
Normal file
143
vendor/sabre/dav/lib/DAV/Xml/Property/ShareAccess.php
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Xml\Property;
|
||||
|
||||
use Sabre\DAV\Sharing\Plugin as SharingPlugin;
|
||||
use Sabre\DAV\Exception\BadRequest;
|
||||
use Sabre\Xml\Element;
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\Writer;
|
||||
|
||||
/**
|
||||
* This class represents the {DAV:}share-access property.
|
||||
*
|
||||
* This property is defined here:
|
||||
* https://tools.ietf.org/html/draft-pot-webdav-resource-sharing-03#section-4.4.1
|
||||
*
|
||||
* This property is used to indicate if a resource is a shared resource, and
|
||||
* whether the instance of the shared resource is the original instance, or
|
||||
* an instance belonging to a sharee.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class ShareAccess implements Element {
|
||||
|
||||
/**
|
||||
* Either SHARED or SHAREDOWNER
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Creates the property.
|
||||
*
|
||||
* The constructor value must be one of the
|
||||
* \Sabre\DAV\Sharing\Plugin::ACCESS_ constants.
|
||||
*
|
||||
* @param int $shareAccess
|
||||
*/
|
||||
function __construct($shareAccess) {
|
||||
|
||||
$this->value = $shareAccess;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current value.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
function getValue() {
|
||||
|
||||
return $this->value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The xmlSerialize method is called during xml writing.
|
||||
*
|
||||
* Use the $writer argument to write its own xml serialization.
|
||||
*
|
||||
* An important note: do _not_ create a parent element. Any element
|
||||
* implementing XmlSerializble should only ever write what's considered
|
||||
* its 'inner xml'.
|
||||
*
|
||||
* The parent of the current element is responsible for writing a
|
||||
* containing element.
|
||||
*
|
||||
* This allows serializers to be re-used for different element names.
|
||||
*
|
||||
* If you are opening new elements, you must also close them again.
|
||||
*
|
||||
* @param Writer $writer
|
||||
* @return void
|
||||
*/
|
||||
function xmlSerialize(Writer $writer) {
|
||||
|
||||
switch ($this->value) {
|
||||
|
||||
case SharingPlugin::ACCESS_NOTSHARED :
|
||||
$writer->writeElement('{DAV:}not-shared');
|
||||
break;
|
||||
case SharingPlugin::ACCESS_SHAREDOWNER :
|
||||
$writer->writeElement('{DAV:}shared-owner');
|
||||
break;
|
||||
case SharingPlugin::ACCESS_READ :
|
||||
$writer->writeElement('{DAV:}read');
|
||||
break;
|
||||
case SharingPlugin::ACCESS_READWRITE :
|
||||
$writer->writeElement('{DAV:}read-write');
|
||||
break;
|
||||
case SharingPlugin::ACCESS_NOACCESS :
|
||||
$writer->writeElement('{DAV:}no-access');
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserialize method is called during xml parsing.
|
||||
*
|
||||
* This method is called statictly, this is because in theory this method
|
||||
* may be used as a type of constructor, or factory method.
|
||||
*
|
||||
* Often you want to return an instance of the current class, but you are
|
||||
* free to return other data as well.
|
||||
*
|
||||
* You are responsible for advancing the reader to the next element. Not
|
||||
* doing anything will result in a never-ending loop.
|
||||
*
|
||||
* If you just want to skip parsing for this element altogether, you can
|
||||
* just call $reader->next();
|
||||
*
|
||||
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @param Reader $reader
|
||||
* @return mixed
|
||||
*/
|
||||
static function xmlDeserialize(Reader $reader) {
|
||||
|
||||
$elems = $reader->parseInnerTree();
|
||||
foreach ($elems as $elem) {
|
||||
switch ($elem['name']) {
|
||||
case '{DAV:}not-shared' :
|
||||
return new self(SharingPlugin::ACCESS_NOTSHARED);
|
||||
case '{DAV:}sharedowner' :
|
||||
return new self(SharingPlugin::ACCESS_SHAREDOWNER);
|
||||
case '{DAV:}read' :
|
||||
return new self(SharingPlugin::ACCESS_READ);
|
||||
case '{DAV:}read-write' :
|
||||
return new self(SharingPlugin::ACCESS_READWRITE);
|
||||
case '{DAV:}no-access' :
|
||||
return new self(SharingPlugin::ACCESS_NOACCESS);
|
||||
}
|
||||
}
|
||||
throw new BadRequest('Invalid value for {DAV:}share-access element');
|
||||
|
||||
}
|
||||
}
|
81
vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php
vendored
Normal file
81
vendor/sabre/dav/lib/DAV/Xml/Request/ShareResource.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAV\Xml\Request;
|
||||
|
||||
use Sabre\Xml\Reader;
|
||||
use Sabre\Xml\XmlDeserializable;
|
||||
use Sabre\DAV\Xml\Element\Sharee;
|
||||
|
||||
/**
|
||||
* ShareResource request parser.
|
||||
*
|
||||
* This class parses the {DAV:}share-resource POST request as defined in:
|
||||
*
|
||||
* https://tools.ietf.org/html/draft-pot-webdav-resource-sharing-01#section-5.3.2.1
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://www.rooftopsolutions.nl/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
class ShareResource implements XmlDeserializable {
|
||||
|
||||
/**
|
||||
* The list of new people added or updated or removed from the share.
|
||||
*
|
||||
* @var Sharee[]
|
||||
*/
|
||||
public $sharees = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Sharee[] $sharees
|
||||
*/
|
||||
function __construct(array $sharees) {
|
||||
|
||||
$this->sharees = $sharees;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The deserialize method is called during xml parsing.
|
||||
*
|
||||
* This method is called statictly, this is because in theory this method
|
||||
* may be used as a type of constructor, or factory method.
|
||||
*
|
||||
* Often you want to return an instance of the current class, but you are
|
||||
* free to return other data as well.
|
||||
*
|
||||
* You are responsible for advancing the reader to the next element. Not
|
||||
* doing anything will result in a never-ending loop.
|
||||
*
|
||||
* If you just want to skip parsing for this element altogether, you can
|
||||
* just call $reader->next();
|
||||
*
|
||||
* $reader->parseInnerTree() will parse the entire sub-tree, and advance to
|
||||
* the next element.
|
||||
*
|
||||
* @param Reader $reader
|
||||
* @return mixed
|
||||
*/
|
||||
static function xmlDeserialize(Reader $reader) {
|
||||
|
||||
$elems = $reader->parseInnerTree([
|
||||
'{DAV:}sharee' => 'Sabre\DAV\Xml\Element\Sharee',
|
||||
'{DAV:}share-access' => 'Sabre\DAV\Xml\Property\ShareAccess',
|
||||
'{DAV:}prop' => 'Sabre\Xml\Deserializer\keyValue',
|
||||
]);
|
||||
|
||||
$sharees = [];
|
||||
|
||||
foreach ($elems as $elem) {
|
||||
if ($elem['name'] !== '{DAV:}sharee') continue;
|
||||
$sharees[] = $elem['value'];
|
||||
|
||||
}
|
||||
|
||||
return new self($sharees);
|
||||
|
||||
}
|
||||
|
||||
}
|
100
vendor/sabre/dav/lib/DAVACL/ACLTrait.php
vendored
Normal file
100
vendor/sabre/dav/lib/DAVACL/ACLTrait.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\DAVACL;
|
||||
|
||||
/**
|
||||
* This trait is a default implementation of the IACL interface.
|
||||
*
|
||||
* In many cases you only want to implement 1 or to of the IACL functions,
|
||||
* this trait allows you to be a bit lazier.
|
||||
*
|
||||
* By default this trait grants all privileges to the owner of the resource.
|
||||
*
|
||||
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
|
||||
* @author Evert Pot (https://evertpot.com/)
|
||||
* @license http://sabre.io/license/ Modified BSD License
|
||||
*/
|
||||
trait ACLTrait {
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function getOwner() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:}all',
|
||||
'principal' => '{DAV:}owner',
|
||||
'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 \Sabre\DAV\Exception\Forbidden('Setting ACL is not supported on this node');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -110,7 +110,7 @@ abstract class AbstractPrincipalCollection extends DAV\Collection implements IPr
|
||||
*
|
||||
* @param string $name
|
||||
* @throws DAV\Exception\NotFound
|
||||
* @return IPrincipal
|
||||
* @return DAV\INode
|
||||
*/
|
||||
function getChild($name) {
|
||||
|
||||
|
52
vendor/sabre/dav/lib/DAVACL/FS/Collection.php
vendored
52
vendor/sabre/dav/lib/DAVACL/FS/Collection.php
vendored
@ -3,6 +3,7 @@
|
||||
namespace Sabre\DAVACL\FS;
|
||||
|
||||
use Sabre\DAV\FSExt\Directory as BaseCollection;
|
||||
use Sabre\DAVACL\ACLTrait;
|
||||
use Sabre\DAVACL\IACL;
|
||||
use Sabre\DAV\Exception\Forbidden;
|
||||
use Sabre\DAV\Exception\NotFound;
|
||||
@ -16,6 +17,8 @@ use Sabre\DAV\Exception\NotFound;
|
||||
*/
|
||||
class Collection extends BaseCollection implements IACL {
|
||||
|
||||
use ACLTrait;
|
||||
|
||||
/**
|
||||
* A list of ACL rules.
|
||||
*
|
||||
@ -52,8 +55,8 @@ class Collection extends BaseCollection implements IACL {
|
||||
* exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @throws DAV\Exception\NotFound
|
||||
* @return DAV\INode
|
||||
* @throws NotFound
|
||||
* @return \Sabre\DAV\INode
|
||||
*/
|
||||
function getChild($name) {
|
||||
|
||||
@ -87,19 +90,6 @@ class Collection extends BaseCollection implements 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.
|
||||
*
|
||||
@ -118,36 +108,4 @@ class Collection extends BaseCollection implements IACL {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Forbidden('Setting ACL is not allowed 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user