add sabre (1.8.x) via composer in the !@#$ place it wants to be
This commit is contained in:
parent
e3504df514
commit
b35122f7a6
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,6 +15,8 @@ compiled/
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
# composer files (for fetching sabre)
|
||||
composer.*
|
||||
|
||||
#ignore documentation, it should be newly built
|
||||
doc/api
|
||||
|
7
vendor/autoload.php
vendored
Normal file
7
vendor/autoload.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit4d84580b3010f36341ea4e8d04bc8eab::getLoader();
|
1
vendor/bin/sabredav
vendored
Symbolic link
1
vendor/bin/sabredav
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../sabre/dav/bin/sabredav
|
1
vendor/bin/vobjectvalidate.php
vendored
Symbolic link
1
vendor/bin/vobjectvalidate.php
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../sabre/vobject/bin/vobjectvalidate.php
|
246
vendor/composer/ClassLoader.php
vendored
Normal file
246
vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0 class loader
|
||||
*
|
||||
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
private $prefixes = array();
|
||||
private $fallbackDirs = array();
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
return call_user_func_array('array_merge', $this->prefixes);
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirs;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of classes, merging with any others previously set.
|
||||
*
|
||||
* @param string $prefix The classes prefix
|
||||
* @param array|string $paths The location(s) of the classes
|
||||
* @param bool $prepend Prepend the location(s)
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirs = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirs
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirs = array_merge(
|
||||
$this->fallbackDirs,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixes[$first][$prefix])) {
|
||||
$this->prefixes[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixes[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixes[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixes[$first][$prefix] = array_merge(
|
||||
$this->prefixes[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of classes, replacing any others previously set.
|
||||
*
|
||||
* @param string $prefix The classes prefix
|
||||
* @param array|string $paths The location(s) of the classes
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirs = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
$this->prefixes[substr($prefix, 0, 1)][$prefix] = (array) $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
include $file;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
|
||||
if ('\\' == $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$classPath = strtr(substr($class, 0, $pos), '\\', DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
$className = substr($class, $pos + 1);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$classPath = null;
|
||||
$className = $class;
|
||||
}
|
||||
|
||||
$classPath .= strtr($className, '_', DIRECTORY_SEPARATOR) . '.php';
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixes[$first])) {
|
||||
foreach ($this->prefixes[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
|
||||
return $dir . DIRECTORY_SEPARATOR . $classPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->fallbackDirs as $dir) {
|
||||
if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
|
||||
return $dir . DIRECTORY_SEPARATOR . $classPath;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return $this->classMap[$class] = false;
|
||||
}
|
||||
}
|
9
vendor/composer/autoload_classmap.php
vendored
Normal file
9
vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
15
vendor/composer/autoload_namespaces.php
vendored
Normal file
15
vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Sabre\\VObject' => array($vendorDir . '/sabre/vobject/lib'),
|
||||
'Sabre\\HTTP' => array($vendorDir . '/sabre/dav/lib'),
|
||||
'Sabre\\DAVACL' => array($vendorDir . '/sabre/dav/lib'),
|
||||
'Sabre\\DAV' => array($vendorDir . '/sabre/dav/lib'),
|
||||
'Sabre\\CardDAV' => array($vendorDir . '/sabre/dav/lib'),
|
||||
'Sabre\\CalDAV' => array($vendorDir . '/sabre/dav/lib'),
|
||||
);
|
43
vendor/composer/autoload_real.php
vendored
Normal file
43
vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit4d84580b3010f36341ea4e8d04bc8eab
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit4d84580b3010f36341ea4e8d04bc8eab', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit4d84580b3010f36341ea4e8d04bc8eab', 'loadClassLoader'));
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
130
vendor/composer/installed.json
vendored
Normal file
130
vendor/composer/installed.json
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
[
|
||||
{
|
||||
"name": "sabre/vobject",
|
||||
"version": "2.1.3",
|
||||
"version_normalized": "2.1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-vobject.git",
|
||||
"reference": "e46d6855cfef23318e7c422cd08d36e344624675"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/e46d6855cfef23318e7c422cd08d36e344624675",
|
||||
"reference": "e46d6855cfef23318e7c422cd08d36e344624675",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=5.3.1"
|
||||
},
|
||||
"time": "2013-10-02 15:57:01",
|
||||
"bin": [
|
||||
"bin/vobjectvalidate.php"
|
||||
],
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Sabre\\VObject": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Evert Pot",
|
||||
"email": "evert@rooftopsolutions.nl",
|
||||
"homepage": "http://evertpot.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects",
|
||||
"homepage": "https://github.com/fruux/sabre-vobject",
|
||||
"keywords": [
|
||||
"VObject",
|
||||
"iCalendar",
|
||||
"vCard"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sabre/dav",
|
||||
"version": "1.8.7",
|
||||
"version_normalized": "1.8.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruux/sabre-dav.git",
|
||||
"reference": "41c750da3c60a427cdd847df090ef0fc7e8f1076"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruux/sabre-dav/zipball/41c750da3c60a427cdd847df090ef0fc7e8f1076",
|
||||
"reference": "41c750da3c60a427cdd847df090ef0fc7e8f1076",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-libxml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-spl": "*",
|
||||
"php": ">=5.3.1",
|
||||
"sabre/vobject": "~2.1.0"
|
||||
},
|
||||
"provide": {
|
||||
"evert/sabredav": "1.7.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"evert/phpdoc-md": "~0.0.7",
|
||||
"phing/phing": "2.4.14",
|
||||
"phpunit/phpunit": "3.7.*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-apc": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"time": "2013-10-02 18:38:26",
|
||||
"bin": [
|
||||
"bin/sabredav"
|
||||
],
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Sabre\\DAV": "lib/",
|
||||
"Sabre\\HTTP": "lib/",
|
||||
"Sabre\\DAVACL": "lib/",
|
||||
"Sabre\\CalDAV": "lib/",
|
||||
"Sabre\\CardDAV": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Evert Pot",
|
||||
"email": "evert@rooftopsolutions.nl",
|
||||
"homepage": "http://evertpot.com/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "WebDAV Framework for PHP",
|
||||
"homepage": "http://code.google.com/p/sabredav/",
|
||||
"keywords": [
|
||||
"CalDAV",
|
||||
"CardDAV",
|
||||
"WebDAV",
|
||||
"framework",
|
||||
"iCalendar"
|
||||
]
|
||||
}
|
||||
]
|
22
vendor/sabre/dav/.gitignore
vendored
Normal file
22
vendor/sabre/dav/.gitignore
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
docs/api
|
||||
docs/wikidocs
|
||||
build.properties
|
||||
build
|
||||
public
|
||||
data
|
||||
fileserver.php
|
||||
fileserver2.php
|
||||
calendarserver.php
|
||||
groupwareserver.php
|
||||
package.xml
|
||||
tmpdata
|
||||
tests/temp
|
||||
tests/.sabredav
|
||||
*.swp
|
||||
composer.lock
|
||||
vendor
|
||||
bin/phing
|
||||
bin/phpunit
|
||||
bin/vobjectvalidate.php
|
||||
bin/phpdocmd
|
||||
bin/phpunit
|
20
vendor/sabre/dav/.travis.yml
vendored
Normal file
20
vendor/sabre/dav/.travis.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
language: php
|
||||
php:
|
||||
- 5.3.3
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
|
||||
services:
|
||||
- mysql
|
||||
|
||||
before_script:
|
||||
- mysql -e 'create database sabredav'
|
||||
- composer install --prefer-source
|
||||
# - echo "zend.enable_gc=0" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
|
||||
|
||||
script:
|
||||
- phpunit --configuration tests/phpunit.xml
|
||||
- cp tests/composer.vobject3.json composer.json
|
||||
- composer update --no-dev
|
||||
- phpunit --configuration tests/phpunit.xml
|
1122
vendor/sabre/dav/ChangeLog
vendored
Normal file
1122
vendor/sabre/dav/ChangeLog
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
vendor/sabre/dav/LICENSE
vendored
Normal file
27
vendor/sabre/dav/LICENSE
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (C) 2007-2013 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.
|
30
vendor/sabre/dav/README.md
vendored
Normal file
30
vendor/sabre/dav/README.md
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# What is SabreDAV
|
||||
|
||||
SabreDAV allows you to easily add WebDAV support to a PHP application. SabreDAV is meant to cover the entire standard, and attempts to allow integration using an easy to understand API.
|
||||
|
||||
### Feature list:
|
||||
|
||||
* Fully WebDAV compliant
|
||||
* Supports Windows XP, Windows Vista, Mac OS/X, DavFSv2, Cadaver, Netdrive, Open Office, and probably more.
|
||||
* Passing all Litmus tests.
|
||||
* Supporting class 1, 2 and 3 Webdav servers.
|
||||
* Locking support.
|
||||
* Custom property support.
|
||||
* CalDAV (tested with [Evolution](http://code.google.com/p/sabredav/wiki/Evolution), [iCal](http://code.google.com/p/sabredav/wiki/ICal), [iPhone](http://code.google.com/p/sabredav/wiki/IPhone) and [Lightning](http://code.google.com/p/sabredav/wiki/Lightning)).
|
||||
* CardDAV (tested with [OS/X addressbook](http://code.google.com/p/sabredav/wiki/OSXAddressbook), the [iOS addressbook](http://code.google.com/p/sabredav/wiki/iOSCardDAV) and [Evolution](http://code.google.com/p/sabredav/wiki/Evolution)).
|
||||
* Over 97% unittest code coverage.
|
||||
|
||||
### Supported RFC's:
|
||||
|
||||
* [RFC2617](http://www.ietf.org/rfc/rfc2617.txt): Basic/Digest auth.
|
||||
* [RFC2518](http://www.ietf.org/rfc/rfc2518.txt): First WebDAV spec.
|
||||
* [RFC3744](http://www.ietf.org/rfc/rfc3744.txt): ACL (some features missing).
|
||||
* [RFC4709](http://www.ietf.org/rfc/rfc4709.txt): [DavMount](http://code.google.com/p/sabredav/wiki/DavMount).
|
||||
* [RFC4791](http://www.ietf.org/rfc/rfc4791.txt): CalDAV.
|
||||
* [RFC4918](http://www.ietf.org/rfc/rfc4918.txt): WebDAV revision.
|
||||
* [RFC5397](http://www.ietf.org/rfc/rfc5689.txt): current-user-principal.
|
||||
* [RFC5689](http://www.ietf.org/rfc/rfc5689.txt): Extended MKCOL.
|
||||
* [RFC5789](http://tools.ietf.org/html/rfc5789): PATCH method for HTTP.
|
||||
* [RFC6352](http://www.ietf.org/rfc/rfc6352.txt): CardDAV
|
||||
* [draft-daboo-carddav-directory-gateway](http://tools.ietf.org/html/draft-daboo-carddav-directory-gateway): CardDAV directory gateway
|
||||
* CalDAV ctag, CalDAV-proxy.
|
248
vendor/sabre/dav/bin/googlecode_upload.py
vendored
Executable file
248
vendor/sabre/dav/bin/googlecode_upload.py
vendored
Executable file
@ -0,0 +1,248 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2006, 2007 Google Inc. All Rights Reserved.
|
||||
# Author: danderson@google.com (David Anderson)
|
||||
#
|
||||
# Script for uploading files to a Google Code project.
|
||||
#
|
||||
# This is intended to be both a useful script for people who want to
|
||||
# streamline project uploads and a reference implementation for
|
||||
# uploading files to Google Code projects.
|
||||
#
|
||||
# To upload a file to Google Code, you need to provide a path to the
|
||||
# file on your local machine, a small summary of what the file is, a
|
||||
# project name, and a valid account that is a member or owner of that
|
||||
# project. You can optionally provide a list of labels that apply to
|
||||
# the file. The file will be uploaded under the same name that it has
|
||||
# in your local filesystem (that is, the "basename" or last path
|
||||
# component). Run the script with '--help' to get the exact syntax
|
||||
# and available options.
|
||||
#
|
||||
# Note that the upload script requests that you enter your
|
||||
# googlecode.com password. This is NOT your Gmail account password!
|
||||
# This is the password you use on googlecode.com for committing to
|
||||
# Subversion and uploading files. You can find your password by going
|
||||
# to http://code.google.com/hosting/settings when logged in with your
|
||||
# Gmail account. If you have already committed to your project's
|
||||
# Subversion repository, the script will automatically retrieve your
|
||||
# credentials from there (unless disabled, see the output of '--help'
|
||||
# for details).
|
||||
#
|
||||
# If you are looking at this script as a reference for implementing
|
||||
# your own Google Code file uploader, then you should take a look at
|
||||
# the upload() function, which is the meat of the uploader. You
|
||||
# basically need to build a multipart/form-data POST request with the
|
||||
# right fields and send it to https://PROJECT.googlecode.com/files .
|
||||
# Authenticate the request using HTTP Basic authentication, as is
|
||||
# shown below.
|
||||
#
|
||||
# Licensed under the terms of the Apache Software License 2.0:
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Questions, comments, feature requests and patches are most welcome.
|
||||
# Please direct all of these to the Google Code users group:
|
||||
# http://groups.google.com/group/google-code-hosting
|
||||
|
||||
"""Google Code file uploader script.
|
||||
"""
|
||||
|
||||
__author__ = 'danderson@google.com (David Anderson)'
|
||||
|
||||
import httplib
|
||||
import os.path
|
||||
import optparse
|
||||
import getpass
|
||||
import base64
|
||||
import sys
|
||||
|
||||
|
||||
def upload(file, project_name, user_name, password, summary, labels=None):
|
||||
"""Upload a file to a Google Code project's file server.
|
||||
|
||||
Args:
|
||||
file: The local path to the file.
|
||||
project_name: The name of your project on Google Code.
|
||||
user_name: Your Google account name.
|
||||
password: The googlecode.com password for your account.
|
||||
Note that this is NOT your global Google Account password!
|
||||
summary: A small description for the file.
|
||||
labels: an optional list of label strings with which to tag the file.
|
||||
|
||||
Returns: a tuple:
|
||||
http_status: 201 if the upload succeeded, something else if an
|
||||
error occurred.
|
||||
http_reason: The human-readable string associated with http_status
|
||||
file_url: If the upload succeeded, the URL of the file on Google
|
||||
Code, None otherwise.
|
||||
"""
|
||||
# The login is the user part of user@gmail.com. If the login provided
|
||||
# is in the full user@domain form, strip it down.
|
||||
if user_name.endswith('@gmail.com'):
|
||||
user_name = user_name[:user_name.index('@gmail.com')]
|
||||
|
||||
form_fields = [('summary', summary)]
|
||||
if labels is not None:
|
||||
form_fields.extend([('label', l.strip()) for l in labels])
|
||||
|
||||
content_type, body = encode_upload_request(form_fields, file)
|
||||
|
||||
upload_host = '%s.googlecode.com' % project_name
|
||||
upload_uri = '/files'
|
||||
auth_token = base64.b64encode('%s:%s'% (user_name, password))
|
||||
headers = {
|
||||
'Authorization': 'Basic %s' % auth_token,
|
||||
'User-Agent': 'Googlecode.com uploader v0.9.4',
|
||||
'Content-Type': content_type,
|
||||
}
|
||||
|
||||
server = httplib.HTTPSConnection(upload_host)
|
||||
server.request('POST', upload_uri, body, headers)
|
||||
resp = server.getresponse()
|
||||
server.close()
|
||||
|
||||
if resp.status == 201:
|
||||
location = resp.getheader('Location', None)
|
||||
else:
|
||||
location = None
|
||||
return resp.status, resp.reason, location
|
||||
|
||||
|
||||
def encode_upload_request(fields, file_path):
|
||||
"""Encode the given fields and file into a multipart form body.
|
||||
|
||||
fields is a sequence of (name, value) pairs. file is the path of
|
||||
the file to upload. The file will be uploaded to Google Code with
|
||||
the same file name.
|
||||
|
||||
Returns: (content_type, body) ready for httplib.HTTP instance
|
||||
"""
|
||||
BOUNDARY = '----------Googlecode_boundary_reindeer_flotilla'
|
||||
CRLF = '\r\n'
|
||||
|
||||
body = []
|
||||
|
||||
# Add the metadata about the upload first
|
||||
for key, value in fields:
|
||||
body.extend(
|
||||
['--' + BOUNDARY,
|
||||
'Content-Disposition: form-data; name="%s"' % key,
|
||||
'',
|
||||
value,
|
||||
])
|
||||
|
||||
# Now add the file itself
|
||||
file_name = os.path.basename(file_path)
|
||||
f = open(file_path, 'rb')
|
||||
file_content = f.read()
|
||||
f.close()
|
||||
|
||||
body.extend(
|
||||
['--' + BOUNDARY,
|
||||
'Content-Disposition: form-data; name="filename"; filename="%s"'
|
||||
% file_name,
|
||||
# The upload server determines the mime-type, no need to set it.
|
||||
'Content-Type: application/octet-stream',
|
||||
'',
|
||||
file_content,
|
||||
])
|
||||
|
||||
# Finalize the form body
|
||||
body.extend(['--' + BOUNDARY + '--', ''])
|
||||
|
||||
return 'multipart/form-data; boundary=%s' % BOUNDARY, CRLF.join(body)
|
||||
|
||||
|
||||
def upload_find_auth(file_path, project_name, summary, labels=None,
|
||||
user_name=None, password=None, tries=3):
|
||||
"""Find credentials and upload a file to a Google Code project's file server.
|
||||
|
||||
file_path, project_name, summary, and labels are passed as-is to upload.
|
||||
|
||||
Args:
|
||||
file_path: The local path to the file.
|
||||
project_name: The name of your project on Google Code.
|
||||
summary: A small description for the file.
|
||||
labels: an optional list of label strings with which to tag the file.
|
||||
config_dir: Path to Subversion configuration directory, 'none', or None.
|
||||
user_name: Your Google account name.
|
||||
tries: How many attempts to make.
|
||||
"""
|
||||
|
||||
while tries > 0:
|
||||
if user_name is None:
|
||||
# Read username if not specified or loaded from svn config, or on
|
||||
# subsequent tries.
|
||||
sys.stdout.write('Please enter your googlecode.com username: ')
|
||||
sys.stdout.flush()
|
||||
user_name = sys.stdin.readline().rstrip()
|
||||
if password is None:
|
||||
# Read password if not loaded from svn config, or on subsequent tries.
|
||||
print 'Please enter your googlecode.com password.'
|
||||
print '** Note that this is NOT your Gmail account password! **'
|
||||
print 'It is the password you use to access Subversion repositories,'
|
||||
print 'and can be found here: http://code.google.com/hosting/settings'
|
||||
password = getpass.getpass()
|
||||
|
||||
status, reason, url = upload(file_path, project_name, user_name, password,
|
||||
summary, labels)
|
||||
# Returns 403 Forbidden instead of 401 Unauthorized for bad
|
||||
# credentials as of 2007-07-17.
|
||||
if status in [httplib.FORBIDDEN, httplib.UNAUTHORIZED]:
|
||||
# Rest for another try.
|
||||
user_name = password = None
|
||||
tries = tries - 1
|
||||
else:
|
||||
# We're done.
|
||||
break
|
||||
|
||||
return status, reason, url
|
||||
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser(usage='googlecode-upload.py -s SUMMARY '
|
||||
'-p PROJECT [options] FILE')
|
||||
parser.add_option('-s', '--summary', dest='summary',
|
||||
help='Short description of the file')
|
||||
parser.add_option('-p', '--project', dest='project',
|
||||
help='Google Code project name')
|
||||
parser.add_option('-u', '--user', dest='user',
|
||||
help='Your Google Code username')
|
||||
parser.add_option('-w', '--password', dest='password',
|
||||
help='Your Google Code password')
|
||||
parser.add_option('-l', '--labels', dest='labels',
|
||||
help='An optional list of comma-separated labels to attach '
|
||||
'to the file')
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if not options.summary:
|
||||
parser.error('File summary is missing.')
|
||||
elif not options.project:
|
||||
parser.error('Project name is missing.')
|
||||
elif len(args) < 1:
|
||||
parser.error('File to upload not provided.')
|
||||
elif len(args) > 1:
|
||||
parser.error('Only one file may be specified.')
|
||||
|
||||
file_path = args[0]
|
||||
|
||||
if options.labels:
|
||||
labels = options.labels.split(',')
|
||||
else:
|
||||
labels = None
|
||||
|
||||
status, reason, url = upload_find_auth(file_path, options.project,
|
||||
options.summary, labels,
|
||||
options.user, options.password)
|
||||
if url:
|
||||
print 'The file was uploaded successfully.'
|
||||
print 'URL: %s' % url
|
||||
return 0
|
||||
else:
|
||||
print 'An error occurred. Your file was not uploaded.'
|
||||
print 'Google Code upload server said: %s (%s)' % (reason, status)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
284
vendor/sabre/dav/bin/migrateto17.php
vendored
Executable file
284
vendor/sabre/dav/bin/migrateto17.php
vendored
Executable file
@ -0,0 +1,284 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
echo "SabreDAV migrate script for version 1.7\n";
|
||||
|
||||
if ($argc<2) {
|
||||
|
||||
echo <<<HELLO
|
||||
|
||||
This script help you migrate from a pre-1.7 database to 1.7 and later\n
|
||||
Both the 'calendarobjects' and 'calendars' tables will be upgraded.
|
||||
|
||||
If you do not have this table, or don't use the default PDO CalDAV backend
|
||||
it's pointless to run this script.
|
||||
|
||||
Keep in mind that some processing will be done on every single record of this
|
||||
table and in addition, ALTER TABLE commands will be executed.
|
||||
If you have a large calendarobjects table, this may mean that this process
|
||||
takes a while.
|
||||
|
||||
Usage:
|
||||
|
||||
php {$argv[0]} [pdo-dsn] [username] [password]
|
||||
|
||||
For example:
|
||||
|
||||
php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password
|
||||
php {$argv[0]} sqlite:data/sabredav.db
|
||||
|
||||
HELLO;
|
||||
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
// There's a bunch of places where the autoloader could be, so we'll try all of
|
||||
// them.
|
||||
$paths = array(
|
||||
__DIR__ . '/../vendor/autoload.php',
|
||||
__DIR__ . '/../../../autoload.php',
|
||||
);
|
||||
|
||||
foreach($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$dsn = $argv[1];
|
||||
$user = isset($argv[2])?$argv[2]:null;
|
||||
$pass = isset($argv[3])?$argv[3]:null;
|
||||
|
||||
echo "Connecting to database: " . $dsn . "\n";
|
||||
|
||||
$pdo = new PDO($dsn, $user, $pass);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
|
||||
echo "Validating existing table layout\n";
|
||||
|
||||
// The only cross-db way to do this, is to just fetch a single record.
|
||||
$row = $pdo->query("SELECT * FROM calendarobjects LIMIT 1")->fetch();
|
||||
|
||||
if (!$row) {
|
||||
echo "Error: This database did not have any records in the calendarobjects table, you should just recreate the table.\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$requiredFields = array(
|
||||
'id',
|
||||
'calendardata',
|
||||
'uri',
|
||||
'calendarid',
|
||||
'lastmodified',
|
||||
);
|
||||
|
||||
foreach($requiredFields as $requiredField) {
|
||||
if (!array_key_exists($requiredField,$row)) {
|
||||
echo "Error: The current 'calendarobjects' table was missing a field we expected to exist.\n";
|
||||
echo "For safety reasons, this process is stopped.\n";
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
$fields17 = array(
|
||||
'etag',
|
||||
'size',
|
||||
'componenttype',
|
||||
'firstoccurence',
|
||||
'lastoccurence',
|
||||
);
|
||||
|
||||
$found = 0;
|
||||
foreach($fields17 as $field) {
|
||||
if (array_key_exists($field, $row)) {
|
||||
$found++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($found === 0) {
|
||||
echo "The database had the 1.6 schema. Table will now be altered.\n";
|
||||
echo "This may take some time for large tables\n";
|
||||
|
||||
switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
|
||||
case 'mysql' :
|
||||
|
||||
$pdo->exec(<<<SQL
|
||||
ALTER TABLE calendarobjects
|
||||
ADD etag VARCHAR(32),
|
||||
ADD size INT(11) UNSIGNED,
|
||||
ADD componenttype VARCHAR(8),
|
||||
ADD firstoccurence INT(11) UNSIGNED,
|
||||
ADD lastoccurence INT(11) UNSIGNED
|
||||
SQL
|
||||
);
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD etag text');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD size integer');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD componenttype TEXT');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD firstoccurence integer');
|
||||
$pdo->exec('ALTER TABLE calendarobjects ADD lastoccurence integer');
|
||||
break;
|
||||
|
||||
default :
|
||||
die('This upgrade script does not support this driver (' . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . ")\n");
|
||||
|
||||
}
|
||||
echo "Database schema upgraded.\n";
|
||||
|
||||
} elseif ($found === 5) {
|
||||
|
||||
echo "Database already had the 1.7 schema\n";
|
||||
|
||||
} else {
|
||||
|
||||
echo "The database had $found out of 5 from the changes for 1.7. This is scary and unusual, so we have to abort.\n";
|
||||
echo "You can manually try to upgrade the schema, and then run this script again.\n";
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
echo "Now, we need to parse every record and pull out some information.\n";
|
||||
|
||||
$result = $pdo->query('SELECT id, calendardata FROM calendarobjects');
|
||||
$stmt = $pdo->prepare('UPDATE calendarobjects SET etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ? WHERE id = ?');
|
||||
|
||||
echo "Total records found: " . $result->rowCount() . "\n";
|
||||
$done = 0;
|
||||
$total = $result->rowCount();
|
||||
while($row = $result->fetch()) {
|
||||
|
||||
try {
|
||||
$newData = getDenormalizedData($row['calendardata']);
|
||||
} catch (Exception $e) {
|
||||
echo "===\nException caught will trying to parser calendarobject.\n";
|
||||
echo "Error message: " . $e->getMessage() . "\n";
|
||||
echo "Record id: " . $row['id'] . "\n";
|
||||
echo "This record is ignored, you should inspect it to see if there's anything wrong.\n===\n";
|
||||
continue;
|
||||
}
|
||||
$stmt->execute(array(
|
||||
$newData['etag'],
|
||||
$newData['size'],
|
||||
$newData['componentType'],
|
||||
$newData['firstOccurence'],
|
||||
$newData['lastOccurence'],
|
||||
$row['id'],
|
||||
));
|
||||
$done++;
|
||||
|
||||
if ($done % 500 === 0) {
|
||||
echo "Completed: $done / $total\n";
|
||||
}
|
||||
}
|
||||
echo "Completed: $done / $total\n";
|
||||
|
||||
echo "Checking the calendars table needs changes.\n";
|
||||
$row = $pdo->query("SELECT * FROM calendars LIMIT 1")->fetch();
|
||||
|
||||
if (array_key_exists('transparent', $row)) {
|
||||
|
||||
echo "The calendars table is already up to date\n";
|
||||
|
||||
} else {
|
||||
|
||||
echo "Adding the 'transparent' field to the calendars table\n";
|
||||
|
||||
switch($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
|
||||
|
||||
case 'mysql' :
|
||||
$pdo->exec("ALTER TABLE calendars ADD transparent TINYINT(1) NOT NULL DEFAULT '0'");
|
||||
break;
|
||||
case 'sqlite' :
|
||||
$pdo->exec("ALTER TABLE calendars ADD transparent bool");
|
||||
break;
|
||||
|
||||
default :
|
||||
die('This upgrade script does not support this driver (' . $pdo->getAttribute(PDO::ATTR_DRIVER_NAME) . ")\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo "Process completed!\n";
|
||||
|
||||
/**
|
||||
* Parses some information from calendar objects, used for optimized
|
||||
* calendar-queries.
|
||||
*
|
||||
* Blantently copied from Sabre\CalDAV\Backend\PDO
|
||||
*
|
||||
* Returns an array with the following keys:
|
||||
* * etag
|
||||
* * size
|
||||
* * componentType
|
||||
* * firstOccurence
|
||||
* * lastOccurence
|
||||
*
|
||||
* @param string $calendarData
|
||||
* @return array
|
||||
*/
|
||||
function getDenormalizedData($calendarData) {
|
||||
|
||||
$vObject = \Sabre\VObject\Reader::read($calendarData);
|
||||
$componentType = null;
|
||||
$component = null;
|
||||
$firstOccurence = null;
|
||||
$lastOccurence = null;
|
||||
foreach($vObject->getComponents() as $component) {
|
||||
if ($component->name!=='VTIMEZONE') {
|
||||
$componentType = $component->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$componentType) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
|
||||
}
|
||||
if ($componentType === 'VEVENT') {
|
||||
$firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
|
||||
// Finding the last occurence is a bit harder
|
||||
if (!isset($component->RRULE)) {
|
||||
if (isset($component->DTEND)) {
|
||||
$lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
|
||||
} elseif (isset($component->DURATION)) {
|
||||
$endDate = clone $component->DTSTART->getDateTime();
|
||||
$endDate->add(\Sabre\VObject\DateTimeParser::parse($component->DURATION->value));
|
||||
$lastOccurence = $endDate->getTimeStamp();
|
||||
} elseif (!$component->DTSTART->hasTime()) {
|
||||
$endDate = clone $component->DTSTART->getDateTime();
|
||||
$endDate->modify('+1 day');
|
||||
$lastOccurence = $endDate->getTimeStamp();
|
||||
} else {
|
||||
$lastOccurence = $firstOccurence;
|
||||
}
|
||||
} else {
|
||||
$it = new \Sabre\VObject\RecurrenceIterator($vObject, (string)$component->UID);
|
||||
$maxDate = new DateTime(\Sabre\CalDAV\Backend\PDO::MAX_DATE);
|
||||
if ($it->isInfinite()) {
|
||||
$lastOccurence = $maxDate->getTimeStamp();
|
||||
} else {
|
||||
$end = $it->getDtEnd();
|
||||
while($it->valid() && $end < $maxDate) {
|
||||
$end = $it->getDtEnd();
|
||||
$it->next();
|
||||
|
||||
}
|
||||
$lastOccurence = $end->getTimeStamp();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'etag' => md5($calendarData),
|
||||
'size' => strlen($calendarData),
|
||||
'componentType' => $componentType,
|
||||
'firstOccurence' => $firstOccurence,
|
||||
'lastOccurence' => $lastOccurence,
|
||||
);
|
||||
|
||||
}
|
140
vendor/sabre/dav/bin/naturalselection.py
vendored
Executable file
140
vendor/sabre/dav/bin/naturalselection.py
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://code.google.com/p/sabredav/wiki/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,treshold):
|
||||
return getfreespace(path)-treshold
|
||||
|
||||
def run(cacheDir, treshold, sleep=5, simulate=False, min_erase = 0):
|
||||
|
||||
bytes = getbytesleft(cacheDir,treshold)
|
||||
if (bytes>0):
|
||||
print "Bytes to go before we hit treshhold:", bytes
|
||||
else:
|
||||
print "Treshold 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 treshold, 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="naturalselecton v0.3",
|
||||
description="Cache directory manager. Deletes cache entries based on accesstime and free space tresholds.\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','--treshold',
|
||||
help="Treshhold in bytes (default = 10737418240, which is 10GB)",
|
||||
type="int",
|
||||
dest="treshold",
|
||||
default=10737418240
|
||||
)
|
||||
parser.add_option(
|
||||
'-m', '--min-erase',
|
||||
help="Minimum number of bytes to erase when the treshold is reached. " +
|
||||
"Setting this option higher will reduce the amount 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,
|
||||
treshold=options.treshold,
|
||||
min_erase=options.min_erase
|
||||
)
|
||||
if runs>0:
|
||||
runs = runs - 1
|
||||
|
||||
if __name__ == '__main__' :
|
||||
main()
|
2
vendor/sabre/dav/bin/sabredav
vendored
Executable file
2
vendor/sabre/dav/bin/sabredav
vendored
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
php -S 0.0.0.0:8080 `dirname $0`/sabredav.php
|
53
vendor/sabre/dav/bin/sabredav.php
vendored
Executable file
53
vendor/sabre/dav/bin/sabredav.php
vendored
Executable file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
// SabreDAV test server.
|
||||
|
||||
class CliLog {
|
||||
|
||||
protected $stream;
|
||||
|
||||
function __construct() {
|
||||
|
||||
$this->stream = fopen('php://stdout','w');
|
||||
|
||||
}
|
||||
|
||||
function log($msg) {
|
||||
fwrite($this->stream, $msg . "\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$log = new CliLog();
|
||||
|
||||
if (php_sapi_name()!=='cli-server') {
|
||||
die("This script is intended to run on the built-in php webserver");
|
||||
}
|
||||
|
||||
// Finding composer
|
||||
|
||||
|
||||
$paths = array(
|
||||
__DIR__ . '/../vendor/autoload.php',
|
||||
__DIR__ . '/../../../autoload.php',
|
||||
);
|
||||
|
||||
foreach($paths as $path) {
|
||||
if (file_exists($path)) {
|
||||
include $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
use Sabre\DAV;
|
||||
|
||||
// Root
|
||||
$root = new DAV\FS\Directory(getcwd());
|
||||
|
||||
// Setting up server.
|
||||
$server = new DAV\Server($root);
|
||||
|
||||
// Browser plugin
|
||||
$server->addPlugin(new DAV\Browser\Plugin());
|
||||
|
||||
$server->exec();
|
79
vendor/sabre/dav/build.xml
vendored
Normal file
79
vendor/sabre/dav/build.xml
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0"?>
|
||||
<project name="SabreDAV" default="buildzip" basedir=".">
|
||||
|
||||
<!-- Any default properties -->
|
||||
<property file="build.properties" />
|
||||
|
||||
<!-- Where to write api documentation -->
|
||||
<property name="sabredav.apidocspath" value="docs/api" />
|
||||
|
||||
<target name="buildzip" depends="init, test, clean">
|
||||
<mkdir dir="build" />
|
||||
<echo>Running composer</echo>
|
||||
<exec command="composer create-project --no-dev sabre/dav build/SabreDAV ${sabredav.version}" checkreturn="false" passthru="1" />
|
||||
<zip destfile="build/SabreDAV-${sabredav.version}.zip" basedir="build/SabreDAV" prefix="SabreDAV/" />
|
||||
</target>
|
||||
|
||||
<target name="uploadzip" depends="buildzip">
|
||||
<echo>Uploading to Google Code</echo>
|
||||
<propertyprompt propertyName="googlecode.username" promptText="Enter your googlecode username" useExistingValue="true" />
|
||||
<propertyprompt propertyName="googlecode.password" promptText="Enter your googlecode password" useExistingValue="true" />
|
||||
<exec command="bin/googlecode_upload.py -s 'SabreDAV ${sabredav.version}' -p sabredav --labels=${sabredav.ucstability} -u '${googlecode.username}' -w '${googlecode.password}' build/SabreDAV-${sabredav.version}.zip" checkreturn="true" />
|
||||
</target>
|
||||
|
||||
<target name="clean" depends="init">
|
||||
<echo msg="Removing build files (cleaning up distribution)" />
|
||||
<delete dir="docs/api" />
|
||||
<delete dir="build" />
|
||||
</target>
|
||||
|
||||
<target name="markrelease" depends="init,clean,test">
|
||||
<echo>Creating Git release tag</echo>
|
||||
<exec command="git tag ${sabredav.version}" checkreturn="false" passthru="1" />
|
||||
</target>
|
||||
|
||||
<target name="test">
|
||||
<phpunit haltonfailure="1" haltonerror="1" bootstrap="tests/bootstrap.php" haltonskipped="1" printsummary="1">
|
||||
<batchtest>
|
||||
<fileset dir="tests">
|
||||
<include name="**/*.php"/>
|
||||
</fileset>
|
||||
</batchtest>
|
||||
</phpunit>
|
||||
</target>
|
||||
|
||||
<target name="apidocs" depends="init">
|
||||
|
||||
<echo>Creating api documentation using PHP documentor</echo>
|
||||
<echo>Writing to ${sabredav.apidocspath}</echo>
|
||||
<exec command="phpdoc parse -t ${sabredav.apidocspath} -d lib/" passthru="1" />
|
||||
<exec command="bin/phpdocmd ${sabredav.apidocspath}/structure.xml ${sabredav.apidocspath} --lt %c" passthru="1" />
|
||||
<!--<delete file="${sabredav.apidocspath}/structure.xml" />-->
|
||||
|
||||
</target>
|
||||
|
||||
<target name="init">
|
||||
|
||||
<!-- This sets SabreDAV version information -->
|
||||
<adhoc-task name="sabredav-version"><![CDATA[
|
||||
|
||||
class SabreDAV_VersionTask extends Task {
|
||||
|
||||
public function main() {
|
||||
|
||||
include_once 'lib/Sabre/DAV/Version.php';
|
||||
$this->getProject()->setNewProperty('sabredav.version',\Sabre\DAV\Version::VERSION);
|
||||
$this->getProject()->setNewProperty('sabredav.stability',\Sabre\DAV\Version::STABILITY);
|
||||
$this->getProject()->setNewProperty('sabredav.ucstability',ucwords(Sabre\DAV\Version::STABILITY));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
]]></adhoc-task>
|
||||
<sabredav-version />
|
||||
<echo>SabreDAV version ${sabredav.version}</echo>
|
||||
|
||||
</target>
|
||||
|
||||
</project>
|
336
vendor/sabre/dav/docs/caldav-ctag.txt
vendored
Normal file
336
vendor/sabre/dav/docs/caldav-ctag.txt
vendored
Normal file
@ -0,0 +1,336 @@
|
||||
|
||||
|
||||
|
||||
Calendar Server Extension C. Daboo
|
||||
Apple
|
||||
May 3, 2007
|
||||
|
||||
|
||||
Calendar Collection Entity Tag (CTag) in CalDAV
|
||||
caldav-ctag-02
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines an extension to CalDAV that provides a
|
||||
fast way for a client to determine whether the contents of a calendar
|
||||
collection may have changed.
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
|
||||
2. Conventions Used in This Document . . . . . . . . . . . . . . . 2
|
||||
3. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
3.1. Server . . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
3.2. Client . . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
4. New features in CalDAV . . . . . . . . . . . . . . . . . . . . 3
|
||||
4.1. getctag WebDAV Property . . . . . . . . . . . . . . . . . . 4
|
||||
5. Security Considerations . . . . . . . . . . . . . . . . . . . . 4
|
||||
6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 5
|
||||
7. Normative References . . . . . . . . . . . . . . . . . . . . . 5
|
||||
Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . . 5
|
||||
Appendix B. Change History . . . . . . . . . . . . . . . . . . . . 5
|
||||
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 6
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 1]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
In CalDAV [RFC4791] calendar data is stored in calendar collection
|
||||
resources. Clients need to "poll" calendar collections in order to
|
||||
find out what has changed since the last time they examined it.
|
||||
Currently that involves having to do a PROPFIND Depth:1 HTTP request,
|
||||
or a CALDAV:calendar-query REPORT request. When a calendar
|
||||
collection contains a large number of calendar resources those
|
||||
operations become expensive on the server.
|
||||
|
||||
Calendar users often configure their clients to poll at short time
|
||||
intervals. So polling traffic to the server will be high, even
|
||||
though the frequency at which changes actually occur to a calendar is
|
||||
typically low.
|
||||
|
||||
To improve on performance, this specification defines a new "calendar
|
||||
collection entity tag" (CTag) WebDAV property that is defined on
|
||||
calendar collections. When the calendar collection changes, the CTag
|
||||
value changes. Thus a client can cache the CTag at some point in
|
||||
time, then poll the collection only (i.e. PROPFIND Depth:0 HTTP
|
||||
requests) and determine if a change has happened based on the
|
||||
returned CTag value. If there is a change, it can then fall back to
|
||||
doing the full (Depth:1) poll of the collection to actually determine
|
||||
which resources in the collection changed.
|
||||
|
||||
This extension also defines CTag's on CalDAV scheduling
|
||||
[I-D.desruisseaux-caldav-sched] Inbox and Outbox collections.
|
||||
|
||||
|
||||
2. Conventions Used in This Document
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
When XML element types in the namespaces "DAV:" and
|
||||
"urn:ietf:params:xml:ns:caldav" are referenced in this document
|
||||
outside of the context of an XML fragment, the string "DAV:" and
|
||||
"CALDAV:" will be prefixed to the element type names respectively.
|
||||
|
||||
The namespace "http://calendarserver.org/ns/" is used for XML
|
||||
elements defined in this specification. When XML element types in
|
||||
this namespace are referenced in this document outside of the context
|
||||
of an XML fragment, the string "CS:" will be prefixed to the element
|
||||
type names respectively.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 2]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
3. Overview
|
||||
|
||||
3.1. Server
|
||||
|
||||
For each calendar or scheduling Inbox or Outbox collection on the
|
||||
server, a new CS:getctag WebDAV property is present.
|
||||
|
||||
The property value is an "opaque" token whose value is guaranteed to
|
||||
be unique over the lifetime of any calendar or scheduling Inbox or
|
||||
Outbox collection at a specific URI.
|
||||
|
||||
Whenever a calendar resource is added to, modified or deleted from
|
||||
the calendar collection, the value of the CS:getctag property MUST
|
||||
change. Typically this change will occur when the DAV:getetag
|
||||
property on a child resource changes due to some protocol action. It
|
||||
could be the result of a change to the body or properties of the
|
||||
resource.
|
||||
|
||||
3.2. Client
|
||||
|
||||
The client starts off with an empty string as the initial value for
|
||||
the cached CTag of a calendar or scheduling Inbox or Outbox
|
||||
collection that it intends to synchronize with.
|
||||
|
||||
When polling a calendar or scheduling Inbox or Outbox collection, the
|
||||
client issues a PROPFIND Depth:0 HTTP request, asking for the CS:
|
||||
getctag property to be returned.
|
||||
|
||||
If the returned value of CS:getctag property matches the one
|
||||
currently cached for the calendar or scheduling Inbox or Outbox
|
||||
collection, then the collection contents have not changed and no
|
||||
further action is required until the next poll.
|
||||
|
||||
If the returned value of CS:getctag property does not match the one
|
||||
found previously, then the contents of the calendar or scheduling
|
||||
Inbox or Outbox collection have changed. At that point the client
|
||||
should re-issue the PROPFIND Depth:1 request to get the collection
|
||||
changes in detail and the CS:getctag property value corresponding to
|
||||
the new state. The new CSgetctag property value should replace the
|
||||
one currently cached for that calendar or scheduling Inbox or Outbox
|
||||
collection.
|
||||
|
||||
|
||||
4. New features in CalDAV
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 3]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
4.1. getctag WebDAV Property
|
||||
|
||||
Name: getctag
|
||||
|
||||
Namespace: http://calendarserver.org/ns/
|
||||
|
||||
Purpose: Specifies a "synchronization" token used to indicate when
|
||||
the contents of a calendar or scheduling Inbox or Outbox
|
||||
collection have changed.
|
||||
|
||||
Conformance: This property MUST be defined on a calendar or
|
||||
scheduling Inbox or Outbox collection resource. It MUST be
|
||||
protected and SHOULD be returned by a PROPFIND DAV:allprop request
|
||||
(as defined in Section 12.14.1 of [RFC2518]).
|
||||
|
||||
Description: The CS:getctag property allows clients to quickly
|
||||
determine if the contents of a calendar or scheduling Inbox or
|
||||
Outbox collection have changed since the last time a
|
||||
"synchronization" operation was done. The CS:getctag property
|
||||
value MUST change each time the contents of the calendar or
|
||||
scheduling Inbox or Outbox collection change, and each change MUST
|
||||
result in a value that is different from any other used with that
|
||||
collection URI.
|
||||
|
||||
Definition:
|
||||
|
||||
<!ELEMENT getctag #PCDATA>
|
||||
|
||||
Example:
|
||||
|
||||
<T:getctag xmlns:T="http://calendarserver.org/ns/"
|
||||
>ABCD-GUID-IN-THIS-COLLECTION-20070228T122324010340</T:getctag>
|
||||
|
||||
|
||||
5. Security Considerations
|
||||
|
||||
The CS:getctag property value changes whenever any resource in the
|
||||
collection or scheduling Inbox or Outbox changes. Thus a change to a
|
||||
resource that a user does not have read access to will result in a
|
||||
change in the CTag and the user will know that a change occurred.
|
||||
However, that user will not able to get additional details about
|
||||
exactly what changed as WebDAV ACLs [RFC3744] will prevent that. So
|
||||
this does expose the fact that there are potentially "hidden"
|
||||
resources in a calendar collection, but it does not expose any
|
||||
details about them.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 4]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
6. IANA Considerations
|
||||
|
||||
This document does not require any actions on the part of IANA.
|
||||
|
||||
|
||||
7. Normative References
|
||||
|
||||
[I-D.desruisseaux-caldav-sched]
|
||||
Desruisseaux, B., "Scheduling Extensions to CalDAV",
|
||||
draft-desruisseaux-caldav-sched-03 (work in progress),
|
||||
January 2007.
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2518] Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D.
|
||||
Jensen, "HTTP Extensions for Distributed Authoring --
|
||||
WEBDAV", RFC 2518, February 1999.
|
||||
|
||||
[RFC3744] Clemm, G., Reschke, J., Sedlar, E., and J. Whitehead, "Web
|
||||
Distributed Authoring and Versioning (WebDAV) Access
|
||||
Control Protocol", RFC 3744, May 2004.
|
||||
|
||||
[RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault,
|
||||
"Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
|
||||
March 2007.
|
||||
|
||||
|
||||
Appendix A. Acknowledgments
|
||||
|
||||
This specification is the result of discussions between the Apple
|
||||
calendar server and client teams.
|
||||
|
||||
|
||||
Appendix B. Change History
|
||||
|
||||
Changes from -01:
|
||||
|
||||
1. Updated to RFC4791 reference.
|
||||
|
||||
2. Added text indicating that ctag applies to schedule Inbox and
|
||||
Outbox as well.
|
||||
|
||||
Changes from -00:
|
||||
|
||||
1. Relaxed requirement so that any type of change to a child
|
||||
resource can trigger a CTag change (similar behavior to ETag).
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 5]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
Author's Address
|
||||
|
||||
Cyrus Daboo
|
||||
Apple Inc.
|
||||
1 Infinite Loop
|
||||
Cupertino, CA 95014
|
||||
USA
|
||||
|
||||
Email: cyrus@daboo.name
|
||||
URI: http://www.apple.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 6]
|
||||
|
1568
vendor/sabre/dav/docs/caldav-notifications.txt
vendored
Normal file
1568
vendor/sabre/dav/docs/caldav-notifications.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
560
vendor/sabre/dav/docs/caldav-proxy.txt
vendored
Normal file
560
vendor/sabre/dav/docs/caldav-proxy.txt
vendored
Normal file
@ -0,0 +1,560 @@
|
||||
|
||||
|
||||
|
||||
Calendar Server Extension C. Daboo
|
||||
Apple Computer
|
||||
May 3, 2007
|
||||
|
||||
|
||||
Calendar User Proxy Functionality in CalDAV
|
||||
caldav-cu-proxy-02
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines an extension to CalDAV that makes it easy
|
||||
for clients to setup and manage calendar user proxies, using the
|
||||
WebDAV Access Control List extension as a basis.
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
|
||||
2. Conventions Used in This Document . . . . . . . . . . . . . . 2
|
||||
3. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
3.1. Server . . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
3.2. Client . . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
4. Open Issues . . . . . . . . . . . . . . . . . . . . . . . . . 4
|
||||
5. New features in CalDAV . . . . . . . . . . . . . . . . . . . . 4
|
||||
5.1. Proxy Principal Resource . . . . . . . . . . . . . . . . . 4
|
||||
5.2. Privilege Provisioning . . . . . . . . . . . . . . . . . . 8
|
||||
6. Security Considerations . . . . . . . . . . . . . . . . . . . 9
|
||||
7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 9
|
||||
8. Normative References . . . . . . . . . . . . . . . . . . . . . 9
|
||||
Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . . 9
|
||||
Appendix B. Change History . . . . . . . . . . . . . . . . . . . 10
|
||||
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 10
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 1]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
CalDAV [RFC4791] provides a way for calendar users to store calendar
|
||||
data and exchange this data via scheduling operations. Based on the
|
||||
WebDAV protocol [RFC2518], it also includes the ability to manage
|
||||
access to calendar data via the WebDAV ACL extension [RFC3744].
|
||||
|
||||
It is often common for a calendar user to delegate some form of
|
||||
responsibility for their calendar and schedules to another calendar
|
||||
user (e.g., a boss allows an assistant to check a calendar or to send
|
||||
and accept scheduling invites on his behalf). The user handling the
|
||||
calendar data on behalf of someone else is often referred to as a
|
||||
"calendar user proxy".
|
||||
|
||||
Whilst CalDAV does have fine-grained access control features that can
|
||||
be used to setup complex sharing and management of calendars, often
|
||||
the proxy behavior required is an "all-or-nothing" approach - i.e.
|
||||
the proxy has access to all the calendars or to no calendars (in
|
||||
which case they are of course not a proxy). So a simple way to
|
||||
manage access to an entire set of calendars and scheduling ability
|
||||
would be handy.
|
||||
|
||||
In addition, calendar user agents will often want to display to a
|
||||
user who has proxy access to their calendars, or to whom they are
|
||||
acting as a proxy. Again, CalDAV's access control discovery and
|
||||
report features can be used to do that, but with fine-grained control
|
||||
that exists, it can be hard to tell who is a "real" proxy as opposed
|
||||
to someone just granted rights to some subset of calendars. Again, a
|
||||
simple way to discover proxy information would be handy.
|
||||
|
||||
|
||||
2. Conventions Used in This Document
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
When XML element types in the namespace "DAV:" are referenced in this
|
||||
document outside of the context of an XML fragment, the string "DAV:"
|
||||
will be prefixed to the element type names.
|
||||
|
||||
When XML element types in the namespaces "DAV:" and
|
||||
"urn:ietf:params:xml:ns:caldav" are referenced in this document
|
||||
outside of the context of an XML fragment, the string "DAV:" and
|
||||
"CALDAV:" will be prefixed to the element type names respectively.
|
||||
|
||||
The namespace "http://calendarserver.org/ns/" is used for XML
|
||||
elements defined in this specification. When XML element types in
|
||||
|
||||
|
||||
|
||||
Daboo [Page 2]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
this namespace are referenced in this document outside of the context
|
||||
of an XML fragment, the string "CS:" will be prefixed to the element
|
||||
type names respectively.
|
||||
|
||||
|
||||
3. Overview
|
||||
|
||||
3.1. Server
|
||||
|
||||
For each calendar user principal on the server, the server will
|
||||
generate two group principals - "proxy groups". One is used to hold
|
||||
the list of principals who have read-only proxy access to the main
|
||||
principal's calendars, the other holds the list of principals who
|
||||
have read-write and scheduling proxy access. NB these new group
|
||||
principals would have no equivalent in Open Directory.
|
||||
|
||||
Privileges on each "proxy group" principal will be set so that the
|
||||
"owner" has the ability to change property values.
|
||||
|
||||
The "proxy group" principals will be child resources of the user
|
||||
principal resource with specific resource types and thus are easy to
|
||||
discover. As a result the user principal resources will also be
|
||||
collection resources.
|
||||
|
||||
When provisioning the calendar user home collection, the server will:
|
||||
|
||||
a. Add an ACE to the calendar home collection giving the read-only
|
||||
"proxy group" inheritable read access.
|
||||
|
||||
b. Add an ACE to the calendar home collection giving the read-write
|
||||
"proxy group" inheritable read-write access.
|
||||
|
||||
c. Add an ACE to each of the calendar Inbox and Outbox collections
|
||||
giving the CALDAV:schedule privilege
|
||||
[I-D.desruisseaux-caldav-sched] to the read-write "proxy group".
|
||||
|
||||
3.2. Client
|
||||
|
||||
A client can see who the proxies are for the current principal by
|
||||
examining the principal resource for the two "proxy group" properties
|
||||
and then looking at the DAV:group-member-set property of each.
|
||||
|
||||
The client can edit the list of proxies for the current principal by
|
||||
editing the DAV:group-member-set property on the relevant "proxy
|
||||
group" principal resource.
|
||||
|
||||
The client can find out who the current principal is a proxy for by
|
||||
running a DAV:principal-match REPORT on the principal collection.
|
||||
|
||||
|
||||
|
||||
Daboo [Page 3]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
Alternatively, the client can find out who the current principal is a
|
||||
proxy for by examining the DAV:group-membership property on the
|
||||
current principal resource looking for membership in other users'
|
||||
"proxy groups".
|
||||
|
||||
|
||||
4. Open Issues
|
||||
|
||||
1. Do we want to separate read-write access to calendars vs the
|
||||
ability to schedule as a proxy?
|
||||
|
||||
2. We may want to restrict changing properties on the proxy group
|
||||
collections to just the DAV:group-member-set property?
|
||||
|
||||
3. There is no way for a proxy to be able to manage the list of
|
||||
proxies. We could allow the main calendar user DAV:write-acl on
|
||||
their "proxy group" principals, in which case they could grant
|
||||
others the right to modify the group membership.
|
||||
|
||||
4. Should the "proxy group" principals also be collections given
|
||||
that the regular principal resources will be?
|
||||
|
||||
|
||||
5. New features in CalDAV
|
||||
|
||||
5.1. Proxy Principal Resource
|
||||
|
||||
Each "regular" principal resource that needs to allow calendar user
|
||||
proxy support MUST be a collection resource. i.e. in addition to
|
||||
including the DAV:principal XML element in the DAV:resourcetype
|
||||
property on the resource, it MUST also include the DAV:collection XML
|
||||
element.
|
||||
|
||||
Each "regular" principal resource MUST contain two child resources
|
||||
with names "calendar-proxy-read" and "calendar-proxy-write" (note
|
||||
that these are only suggested names - the server could choose any
|
||||
unique name for these). These resources are themselves principal
|
||||
resources that are groups contain the list of principals for calendar
|
||||
users who can act as a read-only or read-write proxy respectively.
|
||||
|
||||
The server MUST include the CS:calendar-proxy-read or CS:calendar-
|
||||
proxy-write XML elements in the DAV:resourcetype property of the
|
||||
child resources, respectively. This allows clients to discover the
|
||||
"proxy group" principals by using a PROPFIND, Depth:1 request on the
|
||||
current user's principal resource and requesting the DAV:resourcetype
|
||||
property be returned. The element type declarations are:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 4]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
<!ELEMENT calendar-proxy-read EMPTY>
|
||||
|
||||
<!ELEMENT calendar-proxy-write EMPTY>
|
||||
|
||||
The server MUST allow the "parent" principal to change the DAV:group-
|
||||
member-set property on each of the "child" "proxy group" principal
|
||||
resources. When a principal is listed as a member of the "child"
|
||||
resource, the server MUST include the "child" resource URI in the
|
||||
DAV:group-membership property on the included principal resource.
|
||||
Note that this is just "normal" behavior for a group principal.
|
||||
|
||||
An example principal resource layout might be:
|
||||
|
||||
+ /
|
||||
+ principals/
|
||||
+ users/
|
||||
+ cyrus/
|
||||
calendar-proxy-read
|
||||
calendar-proxy-write
|
||||
+ red/
|
||||
calendar-proxy-read
|
||||
calendar-proxy-write
|
||||
+ wilfredo/
|
||||
calendar-proxy-read
|
||||
calendar-proxy-write
|
||||
|
||||
If the principal "cyrus" wishes to have the principal "red" act as a
|
||||
calendar user proxy on his behalf and have the ability to change
|
||||
items on his calendar or schedule meetings on his behalf, then he
|
||||
would add the principal resource URI for "red" to the DAV:group-
|
||||
member-set property of the principal resource /principals/users/
|
||||
cyrus/calendar-proxy-write, giving:
|
||||
|
||||
<DAV:group-member-set>
|
||||
<DAV:href>/principals/users/red/</DAV:href>
|
||||
</DAV:group-member-set>
|
||||
|
||||
The DAV:group-membership property on the resource /principals/users/
|
||||
red/ would be:
|
||||
|
||||
<DAV:group-membership>
|
||||
<DAV:href>/principals/users/cyrus/calendar-proxy-write</DAV:href>
|
||||
</DAV:group-membership>
|
||||
|
||||
If the principal "red" was also a read-only proxy for the principal
|
||||
"wilfredo", then the DA:group-membership property on the resource
|
||||
/principals/users/red/ would be:
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 5]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
<DAV:group-membership>
|
||||
<DAV:href>/principals/users/cyrus/calendar-proxy-write</DAV:href>
|
||||
<DAV:href>/principals/users/wilfredo/calendar-proxy-read</DAV:href>
|
||||
</DAV:group-membership>
|
||||
|
||||
Thus a client can discover to which principals a particular principal
|
||||
is acting as a calendar user proxy for by examining the DAV:group-
|
||||
membership property.
|
||||
|
||||
An alternative to discovering which principals a user can proxy as is
|
||||
to use the WebDAV ACL principal-match report, targeted at the
|
||||
principal collections available on the server.
|
||||
|
||||
Example:
|
||||
|
||||
>> Request <<
|
||||
|
||||
REPORT /principals/ HTTP/1.1
|
||||
Host: cal.example.com
|
||||
Depth: 0
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
Authorization: Digest username="red",
|
||||
realm="cal.example.com", nonce="...",
|
||||
uri="/principals/", response="...", opaque="..."
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:principal-match xmlns:D="DAV:">
|
||||
<D:self/>
|
||||
<D:prop>
|
||||
<D:resourcetype/>
|
||||
</D:prop>
|
||||
</D:principal-match>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 6]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
>> Response <<
|
||||
|
||||
HTTP/1.1 207 Multi-Status
|
||||
Date: Fri, 10 Nov 2006 09:32:12 GMT
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:multistatus xmlns:D="DAV:"
|
||||
xmlns:A="http://calendarserver.org/ns/">
|
||||
<D:response>
|
||||
<D:href>/principals/users/red/</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype>
|
||||
<D:principal/>
|
||||
<D:collection/>
|
||||
</D:resourcetype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
<D:response>
|
||||
<D:href>/principals/users/cyrus/calendar-proxy-write</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype>
|
||||
<D:principal/>
|
||||
<A:calendar-proxy-write/>
|
||||
</D:resourcetype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
<D:response>
|
||||
<D:href>/principals/users/wilfredo/calendar-proxy-read</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype>
|
||||
<D:principal/>
|
||||
<A:calendar-proxy-read/>
|
||||
</D:resourcetype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
</D:multistatus>
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 7]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
5.2. Privilege Provisioning
|
||||
|
||||
In order for a calendar user proxy to be able to access the calendars
|
||||
of the user they are proxying for the server MUST ensure that the
|
||||
privileges on the relevant calendars are setup accordingly:
|
||||
|
||||
The DAV:read privilege MUST be granted for read-only and read-
|
||||
write calendar user proxy principals
|
||||
|
||||
The DAV:write privilege MUST be granted for read-write calendar
|
||||
user proxy principals.
|
||||
|
||||
Additionally, the CalDAV scheduling Inbox and Outbox calendar
|
||||
collections for the user allowing proxy access, MUST have the CALDAV:
|
||||
schedule privilege [I-D.desruisseaux-caldav-sched] granted for read-
|
||||
write calendar user proxy principals.
|
||||
|
||||
Note that with a suitable repository layout, a server may be able to
|
||||
grant the appropriate privileges on a parent collection and ensure
|
||||
that all the contained collections and resources inherit that. For
|
||||
example, given the following repository layout:
|
||||
|
||||
+ /
|
||||
+ calendars/
|
||||
+ users/
|
||||
+ cyrus/
|
||||
inbox
|
||||
outbox
|
||||
home
|
||||
work
|
||||
+ red/
|
||||
inbox
|
||||
outbox
|
||||
work
|
||||
soccer
|
||||
+ wilfredo/
|
||||
inbox
|
||||
outbox
|
||||
home
|
||||
work
|
||||
flying
|
||||
|
||||
In order for the principal "red" to act as a read-write proxy for the
|
||||
principal "cyrus", the following WebDAV ACE will need to be granted
|
||||
on the resource /calendars/users/cyrus/ and all children of that
|
||||
resource:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 8]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
<DAV:ace>
|
||||
<DAV:principal>
|
||||
<DAV:href>/principals/users/cyrus/calendar-proxy-write</DAV:href>
|
||||
</DAV:principal>
|
||||
<DAV:privileges>
|
||||
<DAV:grant><DAV:read/><DAV:write/></DAV:grant>
|
||||
</DAV:privileges>
|
||||
</DAV:ace>
|
||||
|
||||
|
||||
6. Security Considerations
|
||||
|
||||
TBD
|
||||
|
||||
|
||||
7. IANA Considerations
|
||||
|
||||
This document does not require any actions on the part of IANA.
|
||||
|
||||
|
||||
8. Normative References
|
||||
|
||||
[I-D.desruisseaux-caldav-sched]
|
||||
Desruisseaux, B., "Scheduling Extensions to CalDAV",
|
||||
draft-desruisseaux-caldav-sched-03 (work in progress),
|
||||
January 2007.
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2518] Goland, Y., Whitehead, E., Faizi, A., Carter, S., and D.
|
||||
Jensen, "HTTP Extensions for Distributed Authoring --
|
||||
WEBDAV", RFC 2518, February 1999.
|
||||
|
||||
[RFC3744] Clemm, G., Reschke, J., Sedlar, E., and J. Whitehead, "Web
|
||||
Distributed Authoring and Versioning (WebDAV) Access
|
||||
Control Protocol", RFC 3744, May 2004.
|
||||
|
||||
[RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault,
|
||||
"Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
|
||||
March 2007.
|
||||
|
||||
|
||||
Appendix A. Acknowledgments
|
||||
|
||||
This specification is the result of discussions between the Apple
|
||||
calendar server and client teams.
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 9]
|
||||
|
||||
CalDAV Proxy May 2007
|
||||
|
||||
|
||||
Appendix B. Change History
|
||||
|
||||
Changes from -00:
|
||||
|
||||
1. Updated to RFC 4791 reference.
|
||||
|
||||
Changes from -00:
|
||||
|
||||
1. Added more details on actual CalDAV protocol changes.
|
||||
|
||||
2. Changed namespace from http://apple.com/ns/calendarserver/ to
|
||||
http://calendarserver.org/ns/.
|
||||
|
||||
3. Made "proxy group" principals child resources of their "owner"
|
||||
principals.
|
||||
|
||||
4. The "proxy group" principals now have their own resourcetype.
|
||||
|
||||
|
||||
Author's Address
|
||||
|
||||
Cyrus Daboo
|
||||
Apple Computer, Inc.
|
||||
1 Infinite Loop
|
||||
Cupertino, CA 95014
|
||||
USA
|
||||
|
||||
Email: cyrus@daboo.name
|
||||
URI: http://www.apple.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo [Page 10]
|
||||
|
1624
vendor/sabre/dav/docs/caldav-sharing.txt
vendored
Normal file
1624
vendor/sabre/dav/docs/caldav-sharing.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
560
vendor/sabre/dav/docs/draft-daboo-carddav-directory-gateway-02.txt
vendored
Normal file
560
vendor/sabre/dav/docs/draft-daboo-carddav-directory-gateway-02.txt
vendored
Normal file
@ -0,0 +1,560 @@
|
||||
|
||||
|
||||
|
||||
Network Working Group C. Daboo
|
||||
Internet-Draft Apple Inc.
|
||||
Updates: XXXX-CardDAV August 24, 2010
|
||||
(if approved)
|
||||
Intended status: Standards Track
|
||||
Expires: February 25, 2011
|
||||
|
||||
|
||||
CardDAV Directory Gateway Extension
|
||||
draft-daboo-carddav-directory-gateway-02
|
||||
|
||||
Abstract
|
||||
|
||||
This document defines an extension to the vCard Extensions to WebDAV
|
||||
(CardDAV) protocol that allows a server to expose a directory as a
|
||||
read-only address book collection.
|
||||
|
||||
Status of this Memo
|
||||
|
||||
This Internet-Draft is submitted in full conformance with the
|
||||
provisions of BCP 78 and BCP 79.
|
||||
|
||||
Internet-Drafts are working documents of the Internet Engineering
|
||||
Task Force (IETF). Note that other groups may also distribute
|
||||
working documents as Internet-Drafts. The list of current Internet-
|
||||
Drafts is at http://datatracker.ietf.org/drafts/current/.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six months
|
||||
and may be updated, replaced, or obsoleted by other documents at any
|
||||
time. It is inappropriate to use Internet-Drafts as reference
|
||||
material or to cite them other than as "work in progress."
|
||||
|
||||
This Internet-Draft will expire on February 25, 2011.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2010 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document. Code Components extracted from this document must
|
||||
include Simplified BSD License text as described in Section 4.e of
|
||||
the Trust Legal Provisions and are provided without warranty as
|
||||
described in the Simplified BSD License.
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 1]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction and Overview . . . . . . . . . . . . . . . . . . 3
|
||||
2. Conventions . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
3. CARDDAV:directory-gateway Property . . . . . . . . . . . . . . 4
|
||||
4. XML Element Definitions . . . . . . . . . . . . . . . . . . . 5
|
||||
4.1. CARDDAV:directory . . . . . . . . . . . . . . . . . . . . 5
|
||||
5. Client Guidelines . . . . . . . . . . . . . . . . . . . . . . 5
|
||||
6. Server Guidelines . . . . . . . . . . . . . . . . . . . . . . 6
|
||||
7. Security Considerations . . . . . . . . . . . . . . . . . . . 7
|
||||
8. IANA Consideration . . . . . . . . . . . . . . . . . . . . . . 8
|
||||
9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 8
|
||||
10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 8
|
||||
10.1. Normative References . . . . . . . . . . . . . . . . . . . 8
|
||||
10.2. Informative References . . . . . . . . . . . . . . . . . . 9
|
||||
Appendix A. Change History (to be removed prior to
|
||||
publication as an RFC) . . . . . . . . . . . . . . . 9
|
||||
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 10
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 2]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
1. Introduction and Overview
|
||||
|
||||
The CardDAV [I-D.ietf-vcarddav-carddav] protocol defines a standard
|
||||
way of accessing, managing, and sharing contact information based on
|
||||
the vCard [RFC2426] format. Often, in an enterprise or service
|
||||
provider environment, a directory of all users hosted on the server
|
||||
(or elsewhere) is available (for example via Lightweight Directory
|
||||
Access Protocol (LDAP) [RFC4510] or some direct database access). It
|
||||
would be convenient for CardDAV clients if this directory were
|
||||
exposed as a "global" address book on the CardDAV server so it could
|
||||
be searched in the same way as personal address books are. This
|
||||
specification defines a "directory gateway" feature extension to
|
||||
CardDAV to enable this.
|
||||
|
||||
This specification adds one new WebDAV property to principal
|
||||
resources that contains the URL to one or more directory gateway
|
||||
address book collection resources. It is important for clients to be
|
||||
able to distinguish this address book collection from others because
|
||||
there are specific limitations involved in using it as described
|
||||
below. To aid that, this specification defines an XML element that
|
||||
can be included as a child element of the DAV:resourcetype property
|
||||
of address book collections to identify them as directory gateways.
|
||||
|
||||
Note that this feature is in no way intended to replace full
|
||||
directory access - it is meant to simply provide a convenient way for
|
||||
CardDAV clients to query contact-related attributes in directory
|
||||
records.
|
||||
|
||||
|
||||
2. Conventions
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
The term "protected" is used in the Conformance field of property
|
||||
definitions as defined in Section 15 of [RFC4918].
|
||||
|
||||
This document uses XML DTD fragments ([W3C.REC-xml-20081126], Section
|
||||
3.2) as a purely notational convention. WebDAV request and response
|
||||
bodies cannot be validated by a DTD due to the specific extensibility
|
||||
rules defined in Section 17 of [RFC4918] and due to the fact that all
|
||||
XML elements defined by this specification use the XML namespace name
|
||||
"DAV:". In particular:
|
||||
|
||||
1. element names use the "DAV:" namespace,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 3]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
2. element ordering is irrelevant unless explicitly stated,
|
||||
|
||||
3. extension elements (elements not already defined as valid child
|
||||
elements) may be added anywhere, except when explicitly stated
|
||||
otherwise,
|
||||
|
||||
4. extension attributes (attributes not already defined as valid for
|
||||
this element) may be added anywhere, except when explicitly
|
||||
stated otherwise.
|
||||
|
||||
When XML element types in the namespaces "DAV:" and
|
||||
"urn:ietf:params:xml:ns:carddav" are referenced in this document
|
||||
outside of the context of an XML fragment, the strings "DAV:" and
|
||||
"CARDDAV:" will be prefixed to the element types, respectively.
|
||||
|
||||
|
||||
3. CARDDAV:directory-gateway Property
|
||||
|
||||
Name: directory-gateway
|
||||
|
||||
Namespace: urn:ietf:params:xml:ns:carddav
|
||||
|
||||
Purpose: Identifies URLs of CardDAV address book collections acting
|
||||
as a directory gateway for the server.
|
||||
|
||||
Protected: MUST be protected.
|
||||
|
||||
allprop behavior: SHOULD NOT be returned by a PROPFIND DAV:allprop
|
||||
request.
|
||||
|
||||
Description: The CARDDAV:directory-gateway identifies address book
|
||||
collection resources that are directory gateway address books for
|
||||
the server.
|
||||
|
||||
Definition:
|
||||
|
||||
<!ELEMENT directory-gateway (DAV:href*)>
|
||||
|
||||
Example:
|
||||
|
||||
<C:directory-gateway xmlns:D="DAV:"
|
||||
xmlns:C="urn:ietf:params:xml:ns:carddav">
|
||||
<D:href>/directory</D:href>
|
||||
</C:directory-gateway>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 4]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
4. XML Element Definitions
|
||||
|
||||
4.1. CARDDAV:directory
|
||||
|
||||
Name: directory
|
||||
|
||||
Namespace: urn:ietf:params:xml:ns:carddav
|
||||
|
||||
Purpose: Used to indicate that an address book collection is a
|
||||
directory gateway.
|
||||
|
||||
Description: This element appears in the DAV:resourcetype property
|
||||
on a address book collection resources that are directory
|
||||
gateways. Clients can use the presence of this element to
|
||||
identify directory gateway collections when doing PROPFINDs to
|
||||
list collection contents.
|
||||
|
||||
Definition:
|
||||
|
||||
<!ELEMENT directory EMPTY>
|
||||
|
||||
Example:
|
||||
|
||||
<D:resourcetype xmlns:D="DAV:"
|
||||
xmlns:C="urn:ietf:params:xml:ns:carddav">
|
||||
<D:collection/>
|
||||
<C:addressbook/>
|
||||
<C:directory/>
|
||||
</D:resourcetype>
|
||||
|
||||
|
||||
5. Client Guidelines
|
||||
|
||||
Clients wishing to make use of directory gateway address books can
|
||||
request the CARDDAV:directory-gateway property (Section 3) when
|
||||
examining other properties on the principal resource for the user.
|
||||
If the property is not present, then the directory gateway feature is
|
||||
not supported by the server at that time.
|
||||
|
||||
Clients can also detect the presence of directory gateway address
|
||||
book collections by retrieving the DAV:resourcetype property on
|
||||
collections that it lists, and look for the presence of the CARDDAV:
|
||||
directory element (Section 4.1).
|
||||
|
||||
Since the directory being exposed via a directory gateway address
|
||||
book collection could be large, clients SHOULD limit the number of
|
||||
results returned in an CARDDAV:addressbook-query REPORT as defined in
|
||||
Section 8.6.1 of [I-D.ietf-vcarddav-carddav].
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 5]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
Clients MUST treat the directory gateway address book collection as a
|
||||
read-only collection, so HTTP methods that modify resource data or
|
||||
properties in the address book collection MUST NOT be used.
|
||||
|
||||
Clients SHOULD NOT attempt to cache the entire contents of the
|
||||
directory gateway address book collection resource by retrieving all
|
||||
resources, or trying to examine all the properties of all resources
|
||||
(e.g., via a PROPFIND Depth:1 request). Instead, CARDDAV:
|
||||
addressbook-query REPORTs are used to search for specific address
|
||||
book object resources, and CARDDAV:multiget REPORTs and individual
|
||||
GET requests can be made to retrieve the actual vCard data for
|
||||
address book object resources found via a query.
|
||||
|
||||
When presenting directory gateway collections to the user, clients
|
||||
SHOULD use the DAV:displayname property on the corresponding address
|
||||
book collections as the name of the directory gateway. This is
|
||||
important in the case where more than one directory gateway is
|
||||
available. Clients MAY also provide descriptive information about
|
||||
each directory gateway by examining the CARDDAV:addressbook-
|
||||
description property (see Section 6.2.1 of
|
||||
[I-D.ietf-vcarddav-carddav]) on the resource.
|
||||
|
||||
|
||||
6. Server Guidelines
|
||||
|
||||
Servers wishing to expose a directory gateway as an address book
|
||||
collection MUST include the CARDDAV:directory-gateway property on all
|
||||
principal resources of users expected to use the feature.
|
||||
|
||||
Since the directory being exposed via the directory gateway address
|
||||
book collection could be large, servers SHOULD truncate the number of
|
||||
results returned in an CARDDAV:addressbook-query REPORT as defined in
|
||||
Section 8.6.2 of [I-D.ietf-vcarddav-carddav]. In addition, servers
|
||||
SHOULD disallow requests that effectively enumerate the collection
|
||||
contents (e.g., PROPFIND Depth:1, trivial CARDDAV:addressbook-query,
|
||||
DAV:sync-collection REPORT).
|
||||
|
||||
Servers need to expose the directory information as a set of address
|
||||
book object resources in the directory gateway address book
|
||||
collection resource. To do that, a mapping between the directory
|
||||
record format and the vCard data has to be applied. In general, only
|
||||
directory record attributes that have a direct equivalent in vCard
|
||||
SHOULD be mapped. It is up to individual implementations to
|
||||
determine which attributes to map. But in all cases servers MUST
|
||||
generate valid vCard data as returned to the client. In addition, as
|
||||
required by CardDAV, the UID vCard property MUST be present in the
|
||||
vCard data, and this value MUST be persistent from query to query for
|
||||
the same directory record.
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 6]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
Multiple directory sources could be available to the server. The
|
||||
server MAY use a single directory gateway resource to aggregate
|
||||
results from each directory source. When doing so care is needed
|
||||
when dealing with potential records that refer to the same entity.
|
||||
Servers MAY suppress any duplicates that they are able to determine
|
||||
themselves. Alternatively, multiple directory sources can be exposed
|
||||
as separate directory gateway resources.
|
||||
|
||||
For any directory source, a server MAY expose multiple directory
|
||||
gateway resources where each represents a different query "scope" for
|
||||
the directory. Different scopes MAY be offered to different
|
||||
principals on the server. For example, the server might expose an
|
||||
entire company directory for searching as the resource "/directory-
|
||||
all" to all principals, but then provide "/directory-department-XYZ"
|
||||
as another directory gateway that has a search scope that implicitly
|
||||
limits the search results to just the "XYZ" department. Users in
|
||||
that department would then have a CARDDAV:directory-gateway property
|
||||
on their principal resource that included the "/directory-department-
|
||||
XYZ" resource. Users in other departments would have corresponding
|
||||
directory gateway resources available to them.
|
||||
|
||||
Records in a directory can include data for more than just people,
|
||||
e.g, resources such as rooms or projectors, groups, computer systems
|
||||
etc. It is up to individual implementations to determine the most
|
||||
appropriate "scope" for the data returned via the directory gateway
|
||||
by filtering the appropriate record types. As above, servers could
|
||||
choose to expose people and resources under different directory
|
||||
gateway resources by implicitly limiting the search "scope" for each
|
||||
of those.
|
||||
|
||||
Servers MAY apply implementation defined access rules to determine,
|
||||
on a per-user basis, what records are returned to a particularly user
|
||||
and the content of those records exposed via vCard data. This per-
|
||||
user behavior is in addition to the general security requirements
|
||||
detailed below.
|
||||
|
||||
When multiple directory gateway collections are present, servers
|
||||
SHOULD provide a DAV:displayname property on each that disambiguates
|
||||
them. Servers MAY include a CARDDAV:addressbook-description property
|
||||
(see Section 6.2.1 of [I-D.ietf-vcarddav-carddav]) on each directory
|
||||
gateway resource to provide a description of the directory and any
|
||||
search "scope" that might be used, or any other useful information
|
||||
for users.
|
||||
|
||||
|
||||
7. Security Considerations
|
||||
|
||||
Servers MUST ensure that client requests against the directory
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 7]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
gateway address book collection cannot use excessive resources (CPU,
|
||||
memory, network bandwidth etc), given that the directory could be
|
||||
large.
|
||||
|
||||
Servers MUST take care not to expose sensitive directory record
|
||||
attributes in the vCard data via the directory gateway address book.
|
||||
In general only those properties that have direct correspondence in
|
||||
vCard SHOULD be exposed.
|
||||
|
||||
Servers need to determine whether it is appropriate for the directory
|
||||
information to be available via CardDAV to unauthenticated users. If
|
||||
not, servers MUST ensure that unauthenticated users do not have
|
||||
access to the directory gateway address book object resource and its
|
||||
contents. If unauthenticated access is allowed, servers MAY choose
|
||||
to limit the set of vCard properties that are searchable or returned
|
||||
in the address book object resources when unauthenticated requests
|
||||
are made.
|
||||
|
||||
|
||||
8. IANA Consideration
|
||||
|
||||
This document does not require any actions on the part of IANA.
|
||||
|
||||
|
||||
9. Acknowledgments
|
||||
|
||||
|
||||
10. References
|
||||
|
||||
10.1. Normative References
|
||||
|
||||
[I-D.ietf-vcarddav-carddav]
|
||||
Daboo, C., "vCard Extensions to WebDAV (CardDAV)",
|
||||
draft-ietf-vcarddav-carddav-10 (work in progress),
|
||||
November 2009.
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2426] Dawson, F. and T. Howes, "vCard MIME Directory Profile",
|
||||
RFC 2426, September 1998.
|
||||
|
||||
[RFC4918] Dusseault, L., "HTTP Extensions for Web Distributed
|
||||
Authoring and Versioning (WebDAV)", RFC 4918, June 2007.
|
||||
|
||||
[W3C.REC-xml-20081126]
|
||||
Paoli, J., Yergeau, F., Bray, T., Sperberg-McQueen, C.,
|
||||
and E. Maler, "Extensible Markup Language (XML) 1.0 (Fifth
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 8]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
Edition)", World Wide Web Consortium Recommendation REC-
|
||||
xml-20081126, November 2008,
|
||||
<http://www.w3.org/TR/2008/REC-xml-20081126>.
|
||||
|
||||
10.2. Informative References
|
||||
|
||||
[RFC4510] Zeilenga, K., "Lightweight Directory Access Protocol
|
||||
(LDAP): Technical Specification Road Map", RFC 4510,
|
||||
June 2006.
|
||||
|
||||
|
||||
Appendix A. Change History (to be removed prior to publication as an
|
||||
RFC)
|
||||
|
||||
Changes in -02
|
||||
|
||||
1. Added CARDDAV:directory element for use in DAV:resourcetype
|
||||
|
||||
2. Allow CARDDAV:directory-gateway to be multi-valued
|
||||
|
||||
3. Explain how a server could implicit "scope" queries on different
|
||||
directory gateway resources
|
||||
|
||||
Changes in -01
|
||||
|
||||
1. Remove duplicated text in a couple of sections
|
||||
|
||||
2. Add example of LDAP/generic database as possible directory
|
||||
"sources"
|
||||
|
||||
3. Add text to explain why the client needs to treat this as special
|
||||
and thus the need for a property
|
||||
|
||||
4. Added text to server guidelines indicating requirements for
|
||||
handling vCard UID properties
|
||||
|
||||
5. Added text to server guidelines explain that different record
|
||||
"types" may exist in the directory and the server is free to
|
||||
filter those as appropriate
|
||||
|
||||
6. Added text to server guidelines indicating that server are free
|
||||
to aggregate directory records from multiple sources
|
||||
|
||||
7. Added text to server guidelines indicating that servers are free
|
||||
to apply implementation defined access control to the returned
|
||||
data on a per-user basis
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 9]
|
||||
|
||||
Internet-Draft CardDAV Directory Gateway Extension August 2010
|
||||
|
||||
|
||||
Author's Address
|
||||
|
||||
Cyrus Daboo
|
||||
Apple Inc.
|
||||
1 Infinite Loop
|
||||
Cupertino, CA 95014
|
||||
USA
|
||||
|
||||
Email: cyrus@daboo.name
|
||||
URI: http://www.apple.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Expires February 25, 2011 [Page 10]
|
||||
|
5544
vendor/sabre/dav/docs/draft-desruisseaux-caldav-sched-10.txt
vendored
Normal file
5544
vendor/sabre/dav/docs/draft-desruisseaux-caldav-sched-10.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5152
vendor/sabre/dav/docs/draft-ietf-httpbis-p1-messaging-11.txt
vendored
Normal file
5152
vendor/sabre/dav/docs/draft-ietf-httpbis-p1-messaging-11.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1512
vendor/sabre/dav/docs/draft-ietf-httpbis-p4-conditional-11.txt
vendored
Normal file
1512
vendor/sabre/dav/docs/draft-ietf-httpbis-p4-conditional-11.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1512
vendor/sabre/dav/docs/draft-ietf-httpbis-p5-range-11.txt
vendored
Normal file
1512
vendor/sabre/dav/docs/draft-ietf-httpbis-p5-range-11.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2352
vendor/sabre/dav/docs/draft-ietf-httpbis-p6-cache-11.txt
vendored
Normal file
2352
vendor/sabre/dav/docs/draft-ietf-httpbis-p6-cache-11.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
560
vendor/sabre/dav/docs/draft-nottingham-http-new-status-04.txt
vendored
Normal file
560
vendor/sabre/dav/docs/draft-nottingham-http-new-status-04.txt
vendored
Normal file
@ -0,0 +1,560 @@
|
||||
|
||||
|
||||
|
||||
Network Working Group M. Nottingham
|
||||
Internet-Draft Rackspace
|
||||
Updates: 2616 (if approved) R. Fielding
|
||||
Intended status: Standards Track Adobe
|
||||
Expires: August 7, 2012 February 4, 2012
|
||||
|
||||
|
||||
Additional HTTP Status Codes
|
||||
draft-nottingham-http-new-status-04
|
||||
|
||||
Abstract
|
||||
|
||||
This document specifies additional HyperText Transfer Protocol (HTTP)
|
||||
status codes for a variety of common situations.
|
||||
|
||||
Editorial Note (To be removed by RFC Editor before publication)
|
||||
|
||||
Distribution of this document is unlimited. Although this is not a
|
||||
work item of the HTTPbis Working Group, comments should be sent to
|
||||
the Hypertext Transfer Protocol (HTTP) mailing list at
|
||||
ietf-http-wg@w3.org [1], which may be joined by sending a message
|
||||
with subject "subscribe" to ietf-http-wg-request@w3.org [2].
|
||||
|
||||
Discussions of the HTTPbis Working Group are archived at
|
||||
<http://lists.w3.org/Archives/Public/ietf-http-wg/>.
|
||||
|
||||
Status of this Memo
|
||||
|
||||
This Internet-Draft is submitted in full conformance with the
|
||||
provisions of BCP 78 and BCP 79.
|
||||
|
||||
Internet-Drafts are working documents of the Internet Engineering
|
||||
Task Force (IETF). Note that other groups may also distribute
|
||||
working documents as Internet-Drafts. The list of current Internet-
|
||||
Drafts is at http://datatracker.ietf.org/drafts/current/.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six months
|
||||
and may be updated, replaced, or obsoleted by other documents at any
|
||||
time. It is inappropriate to use Internet-Drafts as reference
|
||||
material or to cite them other than as "work in progress."
|
||||
|
||||
This Internet-Draft will expire on August 7, 2012.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2012 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 1]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document. Code Components extracted from this document must
|
||||
include Simplified BSD License text as described in Section 4.e of
|
||||
the Trust Legal Provisions and are provided without warranty as
|
||||
described in the Simplified BSD License.
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
2. Requirements . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
3. 428 Precondition Required . . . . . . . . . . . . . . . . . . . 3
|
||||
4. 429 Too Many Requests . . . . . . . . . . . . . . . . . . . . . 4
|
||||
5. 431 Request Header Fields Too Large . . . . . . . . . . . . . . 4
|
||||
6. 511 Network Authentication Required . . . . . . . . . . . . . . 5
|
||||
7. Security Considerations . . . . . . . . . . . . . . . . . . . . 6
|
||||
8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 7
|
||||
9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 8
|
||||
9.1. Normative References . . . . . . . . . . . . . . . . . . . 8
|
||||
9.2. Informative References . . . . . . . . . . . . . . . . . . 8
|
||||
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . . 8
|
||||
Appendix B. Issues Raised by Captive Portals . . . . . . . . . . . 8
|
||||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 9
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 2]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
This document specifies additional HTTP [RFC2616] status codes for a
|
||||
variety of common situations, to improve interoperability and avoid
|
||||
confusion when other, less precise status codes are used.
|
||||
|
||||
Note that these status codes are optional; servers cannot be required
|
||||
to support them. However, because clients will treat unknown status
|
||||
codes as a generic error of the same class (e.g., 499 is treated as
|
||||
400 if it is not recognized), they can be safely deployed by existing
|
||||
servers (see [RFC2616] Section 6.1.1 for more information).
|
||||
|
||||
|
||||
2. Requirements
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
|
||||
3. 428 Precondition Required
|
||||
|
||||
The 428 status code indicates that the origin server requires the
|
||||
request to be conditional.
|
||||
|
||||
Its typical use is to avoid the "lost update" problem, where a client
|
||||
GETs a resource's state, modifies it, and PUTs it back to the server,
|
||||
when meanwhile a third party has modified the state on the server,
|
||||
leading to a conflict. By requiring requests to be conditional, the
|
||||
server can assure that clients are working with the correct copies.
|
||||
|
||||
Responses using this status code SHOULD explain how to resubmit the
|
||||
request successfully. For example:
|
||||
|
||||
HTTP/1.1 428 Precondition Required
|
||||
Content-Type: text/html
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Precondition Required</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Precondition Required</h1>
|
||||
<p>This request is required to be conditional;
|
||||
try using "If-Match".</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 3]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
Responses with the 428 status code MUST NOT be stored by a cache.
|
||||
|
||||
|
||||
4. 429 Too Many Requests
|
||||
|
||||
The 429 status code indicates that the user has sent too many
|
||||
requests in a given amount of time ("rate limiting").
|
||||
|
||||
The response representations SHOULD include details explaining the
|
||||
condition, and MAY include a Retry-After header indicating how long
|
||||
to wait before making a new request.
|
||||
|
||||
For example:
|
||||
|
||||
HTTP/1.1 429 Too Many Requests
|
||||
Content-Type: text/html
|
||||
Retry-After: 3600
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Too Many Requests</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Too Many Requests</h1>
|
||||
<p>I only allow 50 requests per hour to this Web site per
|
||||
logged in user. Try again soon.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Note that this specification does not define how the origin server
|
||||
identifies the user, nor how it counts requests. For example, an
|
||||
origin server that is limiting request rates can do so based upon
|
||||
counts of requests on a per-resource basis, across the entire server,
|
||||
or even among a set of servers. Likewise, it might identify the user
|
||||
by its authentication credentials, or a stateful cookie.
|
||||
|
||||
Responses with the 429 status code MUST NOT be stored by a cache.
|
||||
|
||||
|
||||
5. 431 Request Header Fields Too Large
|
||||
|
||||
The 431 status code indicates that the server is unwilling to process
|
||||
the request because its header fields are too large. The request MAY
|
||||
be resubmitted after reducing the size of the request header fields.
|
||||
|
||||
It can be used both when the set of request header fields in total
|
||||
are too large, and when a single header field is at fault. In the
|
||||
latter case, the response representation SHOULD specify which header
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 4]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
field was too large.
|
||||
|
||||
For example:
|
||||
|
||||
HTTP/1.1 431 Request Header Fields Too Large
|
||||
Content-Type: text/html
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Request Header Fields Too Large</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Request Header Fields Too Large</h1>
|
||||
<p>The "Example" header was too large.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Responses with the 431 status code MUST NOT be stored by a cache.
|
||||
|
||||
|
||||
6. 511 Network Authentication Required
|
||||
|
||||
The 511 status code indicates that the client needs to authenticate
|
||||
to gain network access.
|
||||
|
||||
The response representation SHOULD contain a link to a resource that
|
||||
allows the user to submit credentials (e.g. with a HTML form).
|
||||
|
||||
Note that the 511 response SHOULD NOT contain a challenge or the
|
||||
login interface itself, because browsers would show the login
|
||||
interface as being associated with the originally requested URL,
|
||||
which may cause confusion.
|
||||
|
||||
The 511 status SHOULD NOT be generated by origin servers; it is
|
||||
intended for use by intercepting proxies that are interposed as a
|
||||
means of controlling access to the network.
|
||||
|
||||
Responses with the 511 status code MUST NOT be stored by a cache.
|
||||
|
||||
6.1. The 511 Status Code and Captive Portals
|
||||
|
||||
The 511 status code is designed to mitigate problems caused by
|
||||
"captive portals" to software (especially non-browser agents) that is
|
||||
expecting a response from the server that a request was made to, not
|
||||
the intervening network infrastructure. It is not intended to
|
||||
encouraged deployment of captive portals, only to limit the damage
|
||||
caused by them.
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 5]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
A network operator wishing to require some authentication, acceptance
|
||||
of terms or other user interaction before granting access usually
|
||||
does so by identifing clients who have not done so ("unknown
|
||||
clients") using their MAC addresses.
|
||||
|
||||
Unknown clients then have all traffic blocked, except for that on TCP
|
||||
port 80, which is sent to a HTTP server (the "login server")
|
||||
dedicated to "logging in" unknown clients, and of course traffic to
|
||||
the login server itself.
|
||||
|
||||
For example, a user agent might connect to a network and make the
|
||||
following HTTP request on TCP port 80:
|
||||
|
||||
GET /index.htm HTTP/1.1
|
||||
Host: www.example.com
|
||||
|
||||
Upon receiving such a request, the login server would generate a 511
|
||||
response:
|
||||
|
||||
HTTP/1.1 511 Network Authentication Required
|
||||
Content-Type: text/html
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Network Authentication Required</title>
|
||||
<meta http-equiv="refresh"
|
||||
content="0; url=https://login.example.net/">
|
||||
</head>
|
||||
<body>
|
||||
<p>You need to <a href="https://login.example.net/">
|
||||
authenticate with the local network</a> in order to gain
|
||||
access.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Here, the 511 status code assures that non-browser clients will not
|
||||
interpret the response as being from the origin server, and the META
|
||||
HTML element redirects the user agent to the login server.
|
||||
|
||||
|
||||
7. Security Considerations
|
||||
|
||||
7.1. 428 Precondition Required
|
||||
|
||||
The 428 status code is optional; clients cannot rely upon its use to
|
||||
prevent "lost update" conflicts.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 6]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
7.2. 429 Too Many Requests
|
||||
|
||||
When a server is under attack or just receiving a very large number
|
||||
of requests from a single party, responding to each with a 429 status
|
||||
code will consume resources.
|
||||
|
||||
Therefore, servers are not required to use the 429 status code; when
|
||||
limiting resource usage, it may be more appropriate to just drop
|
||||
connections, or take other steps.
|
||||
|
||||
7.3. 431 Request Header Fields Too Large
|
||||
|
||||
Servers are not required to use the 431 status code; when under
|
||||
attack, it may be more appropriate to just drop connections, or take
|
||||
other steps.
|
||||
|
||||
7.4. 511 Network Authentication Required
|
||||
|
||||
In common use, a response carrying the 511 status code will not come
|
||||
from the origin server indicated in the request's URL. This presents
|
||||
many security issues; e.g., an attacking intermediary may be
|
||||
inserting cookies into the original domain's name space, may be
|
||||
observing cookies or HTTP authentication credentials sent from the
|
||||
user agent, and so on.
|
||||
|
||||
However, these risks are not unique to the 511 status code; in other
|
||||
words, a captive portal that is not using this status code introduces
|
||||
the same issues.
|
||||
|
||||
Also, note that captive portals using this status code on an SSL or
|
||||
TLS connection (commonly, port 443) will generate a certificate error
|
||||
on the client.
|
||||
|
||||
|
||||
8. IANA Considerations
|
||||
|
||||
The HTTP Status Codes Registry should be updated with the following
|
||||
entries:
|
||||
|
||||
o Code: 428
|
||||
o Description: Precondition Required
|
||||
o Specification: [ this document ]
|
||||
|
||||
o Code: 429
|
||||
o Description: Too Many Requests
|
||||
o Specification: [ this document ]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 7]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
o Code: 431
|
||||
o Description: Request Header Fields Too Large
|
||||
o Specification: [ this document ]
|
||||
|
||||
o Code: 511
|
||||
o Description: Network Authentication Required
|
||||
o Specification: [ this document ]
|
||||
|
||||
|
||||
9. References
|
||||
|
||||
9.1. Normative References
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
|
||||
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
|
||||
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
|
||||
|
||||
9.2. Informative References
|
||||
|
||||
[RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault,
|
||||
"Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
|
||||
March 2007.
|
||||
|
||||
[RFC4918] Dusseault, L., "HTTP Extensions for Web Distributed
|
||||
Authoring and Versioning (WebDAV)", RFC 4918, June 2007.
|
||||
|
||||
URIs
|
||||
|
||||
[1] <mailto:ietf-http-wg@w3.org>
|
||||
|
||||
[2] <mailto:ietf-http-wg-request@w3.org?subject=subscribe>
|
||||
|
||||
|
||||
Appendix A. Acknowledgements
|
||||
|
||||
Thanks to Jan Algermissen and Julian Reschke for their suggestions
|
||||
and feedback.
|
||||
|
||||
|
||||
Appendix B. Issues Raised by Captive Portals
|
||||
|
||||
Since clients cannot differentiate between a portal's response and
|
||||
that of the HTTP server that they intended to communicate with, a
|
||||
number of issues arise. The 511 status code is intended to help
|
||||
mitigate some of them.
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 8]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
One example is the "favicon.ico"
|
||||
<http://en.wikipedia.org/wiki/Favicon> commonly used by browsers to
|
||||
identify the site being accessed. If the favicon for a given site is
|
||||
fetched from a captive portal instead of the intended site (e.g.,
|
||||
because the user is unauthenticated), it will often "stick" in the
|
||||
browser's cache (most implementations cache favicons aggressively)
|
||||
beyond the portal session, so that it seems as if the portal's
|
||||
favicon has "taken over" the legitimate site.
|
||||
|
||||
Another browser-based issue comes about when P3P
|
||||
<http://www.w3.org/TR/P3P/> is supported. Depending on how it is
|
||||
implemented, it's possible a browser might interpret a portal's
|
||||
response for the p3p.xml file as the server's, resulting in the
|
||||
privacy policy (or lack thereof) advertised by the portal being
|
||||
interpreted as applying to the intended site. Other Web-based
|
||||
protocols such as WebFinger
|
||||
<http://code.google.com/p/webfinger/wiki/WebFingerProtocol>, CORS
|
||||
<http://www.w3.org/TR/cors/> and OAuth
|
||||
<http://tools.ietf.org/html/draft-ietf-oauth-v2> may also be
|
||||
vulnerable to such issues.
|
||||
|
||||
Although HTTP is most widely used with Web browsers, a growing number
|
||||
of non-browsing applications use it as a substrate protocol. For
|
||||
example, WebDAV [RFC4918] and CalDAV [RFC4791] both use HTTP as the
|
||||
basis (for remote authoring and calendaring, respectively). Using
|
||||
these applications from behind a captive portal can result in
|
||||
spurious errors being presented to the user, and might result in
|
||||
content corruption, in extreme cases.
|
||||
|
||||
Similarly, other non-browser applications using HTTP can be affected
|
||||
as well; e.g., widgets <http://www.w3.org/TR/widgets/>, software
|
||||
updates, and other specialised software such as Twitter clients and
|
||||
the iTunes Music Store.
|
||||
|
||||
It should be noted that it's sometimes believed that using HTTP
|
||||
redirection to direct traffic to the portal addresses these issues.
|
||||
However, since many of these uses "follow" redirects, this is not a
|
||||
good solution.
|
||||
|
||||
|
||||
Authors' Addresses
|
||||
|
||||
Mark Nottingham
|
||||
Rackspace
|
||||
|
||||
Email: mnot@mnot.net
|
||||
URI: http://www.mnot.net/
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 9]
|
||||
|
||||
Internet-Draft Additional HTTP Status Codes February 2012
|
||||
|
||||
|
||||
Roy T. Fielding
|
||||
Adobe Systems Incorporated
|
||||
345 Park Ave
|
||||
San Jose, CA 95110
|
||||
USA
|
||||
|
||||
Email: fielding@gbiv.com
|
||||
URI: http://roy.gbiv.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Fielding Expires August 7, 2012 [Page 10]
|
||||
|
1851
vendor/sabre/dav/docs/rfc2425.txt
vendored
Normal file
1851
vendor/sabre/dav/docs/rfc2425.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2355
vendor/sabre/dav/docs/rfc2426.txt
vendored
Normal file
2355
vendor/sabre/dav/docs/rfc2426.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5267
vendor/sabre/dav/docs/rfc2518.txt
vendored
Normal file
5267
vendor/sabre/dav/docs/rfc2518.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9859
vendor/sabre/dav/docs/rfc2616.txt
vendored
Normal file
9859
vendor/sabre/dav/docs/rfc2616.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1907
vendor/sabre/dav/docs/rfc2617.txt
vendored
Normal file
1907
vendor/sabre/dav/docs/rfc2617.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10329
vendor/sabre/dav/docs/rfc3253.pdf
vendored
Normal file
10329
vendor/sabre/dav/docs/rfc3253.pdf
vendored
Normal file
File diff suppressed because one or more lines are too long
6295
vendor/sabre/dav/docs/rfc3744.pdf
vendored
Normal file
6295
vendor/sabre/dav/docs/rfc3744.pdf
vendored
Normal file
File diff suppressed because one or more lines are too long
3127
vendor/sabre/dav/docs/rfc4437.pdf
vendored
Normal file
3127
vendor/sabre/dav/docs/rfc4437.pdf
vendored
Normal file
File diff suppressed because one or more lines are too long
1459
vendor/sabre/dav/docs/rfc4790.txt
vendored
Normal file
1459
vendor/sabre/dav/docs/rfc4790.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5995
vendor/sabre/dav/docs/rfc4791.txt
vendored
Normal file
5995
vendor/sabre/dav/docs/rfc4791.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13609
vendor/sabre/dav/docs/rfc4918.pdf
vendored
Normal file
13609
vendor/sabre/dav/docs/rfc4918.pdf
vendored
Normal file
File diff suppressed because one or more lines are too long
395
vendor/sabre/dav/docs/rfc5051.txt
vendored
Normal file
395
vendor/sabre/dav/docs/rfc5051.txt
vendored
Normal file
@ -0,0 +1,395 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group M. Crispin
|
||||
Request for Comments: 5051 University of Washington
|
||||
Category: Standards Track October 2007
|
||||
|
||||
|
||||
i;unicode-casemap - Simple Unicode Collation Algorithm
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This document specifies an Internet standards track protocol for the
|
||||
Internet community, and requests discussion and suggestions for
|
||||
improvements. Please refer to the current edition of the "Internet
|
||||
Official Protocol Standards" (STD 1) for the standardization state
|
||||
and status of this protocol. Distribution of this memo is unlimited.
|
||||
|
||||
Abstract
|
||||
|
||||
This document describes "i;unicode-casemap", a simple case-
|
||||
insensitive collation for Unicode strings. It provides equality,
|
||||
substring, and ordering operations.
|
||||
|
||||
1. Introduction
|
||||
|
||||
The "i;ascii-casemap" collation described in [COMPARATOR] is quite
|
||||
simple to implement and provides case-independent comparisons for the
|
||||
26 Latin alphabetics. It is specified as the default and/or baseline
|
||||
comparator in some application protocols, e.g., [IMAP-SORT].
|
||||
|
||||
However, the "i;ascii-casemap" collation does not produce
|
||||
satisfactory results with non-ASCII characters. It is possible, with
|
||||
a modest extension, to provide a more sophisticated collation with
|
||||
greater multilingual applicability than "i;ascii-casemap". This
|
||||
extension provides case-independent comparisons for a much greater
|
||||
number of characters. It also collates characters with diacriticals
|
||||
with the non-diacritical character forms.
|
||||
|
||||
This collation, "i;unicode-casemap", is intended to be an alternative
|
||||
to, and preferred over, "i;ascii-casemap". It does not replace the
|
||||
"i;basic" collation described in [BASIC].
|
||||
|
||||
2. Unicode Casemap Collation Description
|
||||
|
||||
The "i;unicode-casemap" collation is a simple collation which is
|
||||
case-insensitive in its treatment of characters. It provides
|
||||
equality, substring, and ordering operations. The validity test
|
||||
operation returns "valid" for any input.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 1]
|
||||
|
||||
RFC 5051 i;unicode-casemap October 2007
|
||||
|
||||
|
||||
This collation allows strings in arbitrary (and mixed) character
|
||||
sets, as long as the character set for each string is identified and
|
||||
it is possible to convert the string to Unicode. Strings which have
|
||||
an unidentified character set and/or cannot be converted to Unicode
|
||||
are not rejected, but are treated as binary.
|
||||
|
||||
Each input string is prepared by converting it to a "titlecased
|
||||
canonicalized UTF-8" string according to the following steps, using
|
||||
UnicodeData.txt ([UNICODE-DATA]):
|
||||
|
||||
(1) A Unicode codepoint is obtained from the input string.
|
||||
|
||||
(a) If the input string is in a known charset that can be
|
||||
converted to Unicode, a sequence in the string's charset
|
||||
is read and checked for validity according to the rules of
|
||||
that charset. If the sequence is valid, it is converted
|
||||
to a Unicode codepoint. Note that for input strings in
|
||||
UTF-8, the UTF-8 sequence must be valid according to the
|
||||
rules of [UTF-8]; e.g., overlong UTF-8 sequences are
|
||||
invalid.
|
||||
|
||||
(b) If the input string is in an unknown charset, or an
|
||||
invalid sequence occurs in step (1)(a), conversion ceases.
|
||||
No further preparation is performed, and any partial
|
||||
preparation results are discarded. The original string is
|
||||
used unchanged with the i;octet comparator.
|
||||
|
||||
(2) The following steps, using UnicodeData.txt ([UNICODE-DATA]),
|
||||
are performed on the resulting codepoint from step (1)(a).
|
||||
|
||||
(a) If the codepoint has a titlecase property in
|
||||
UnicodeData.txt (this is normally the same as the
|
||||
uppercase property), the codepoint is converted to the
|
||||
codepoints in the titlecase property.
|
||||
|
||||
(b) If the resulting codepoint from (2)(a) has a decomposition
|
||||
property of any type in UnicodeData.txt, the codepoint is
|
||||
converted to the codepoints in the decomposition property.
|
||||
This step is recursively applied to each of the resulting
|
||||
codepoints until no more decomposition is possible
|
||||
(effectively Normalization Form KD).
|
||||
|
||||
Example: codepoint U+01C4 (LATIN CAPITAL LETTER DZ WITH CARON)
|
||||
has a titlecase property of U+01C5 (LATIN CAPITAL LETTER D
|
||||
WITH SMALL LETTER Z WITH CARON). Codepoint U+01C5 has a
|
||||
decomposition property of U+0044 (LATIN CAPITAL LETTER D)
|
||||
U+017E (LATIN SMALL LETTER Z WITH CARON). U+017E has a
|
||||
decomposition property of U+007A (LATIN SMALL LETTER Z) U+030c
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 2]
|
||||
|
||||
RFC 5051 i;unicode-casemap October 2007
|
||||
|
||||
|
||||
(COMBINING CARON). Neither U+0044, U+007A, nor U+030C have
|
||||
any decomposition properties. Therefore, U+01C4 is converted
|
||||
to U+0044 U+007A U+030C by this step.
|
||||
|
||||
(3) The resulting codepoint(s) from step (2) is/are appended, in
|
||||
UTF-8 format, to the "titlecased canonicalized UTF-8" string.
|
||||
|
||||
(4) Repeat from step (1) until there is no more data in the input
|
||||
string.
|
||||
|
||||
Following the above preparation process on each string, the equality,
|
||||
ordering, and substring operations are as for i;octet.
|
||||
|
||||
It is permitted to use an alternative implementation of the above
|
||||
preparation process if it produces the same results. For example, it
|
||||
may be more convenient for an implementation to convert all input
|
||||
strings to a sequence of UTF-16 or UTF-32 values prior to performing
|
||||
any of the step (2) actions. Similarly, if all input strings are (or
|
||||
are convertible to) Unicode, it may be possible to use UTF-32 as an
|
||||
alternative to UTF-8 in step (3).
|
||||
|
||||
Note: UTF-16 is unsuitable as an alternative to UTF-8 in step (3),
|
||||
because UTF-16 surrogates will cause i;octet to collate codepoints
|
||||
U+E0000 through U+FFFF after non-BMP codepoints.
|
||||
|
||||
This collation is not locale sensitive. Consequently, care should be
|
||||
taken when using OS-supplied functions to implement this collation.
|
||||
Functions such as strcasecmp and toupper are sometimes locale
|
||||
sensitive and may inconsistently casemap letters.
|
||||
|
||||
The i;unicode-casemap collation is well suited to use with many
|
||||
Internet protocols and computer languages. Use with natural language
|
||||
is often inappropriate; even though the collation apparently supports
|
||||
languages such as Swahili and English, in real-world use it tends to
|
||||
mis-sort a number of types of string:
|
||||
|
||||
o people and place names containing scripts that are not collated
|
||||
according to "alphabetical order".
|
||||
o words with characters that have diacriticals. However,
|
||||
i;unicode-casemap generally does a better job than i;ascii-casemap
|
||||
for most (but not all) languages. For example, German umlaut
|
||||
letters will sort correctly, but some Scandinavian letters will
|
||||
not.
|
||||
o names such as "Lloyd" (which in Welsh sorts after "Lyon", unlike
|
||||
in English),
|
||||
o strings containing other non-letter symbols; e.g., euro and pound
|
||||
sterling symbols, quotation marks other than '"', dashes/hyphens,
|
||||
etc.
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 3]
|
||||
|
||||
RFC 5051 i;unicode-casemap October 2007
|
||||
|
||||
|
||||
3. Unicode Casemap Collation Registration
|
||||
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE collation SYSTEM 'collationreg.dtd'>
|
||||
<collation rfc="5051" scope="global" intendedUse="common">
|
||||
<identifier>i;unicode-casemap</identifier>
|
||||
<title>Unicode Casemap</title>
|
||||
<operations>equality order substring</operations>
|
||||
<specification>RFC 5051</specification>
|
||||
<owner>IETF</owner>
|
||||
<submitter>mrc@cac.washington.edu</submitter>
|
||||
</collation>
|
||||
|
||||
4. Security Considerations
|
||||
|
||||
The security considerations for [UTF-8], [STRINGPREP], and [UNICODE-
|
||||
SECURITY] apply and are normative to this specification.
|
||||
|
||||
The results from this comparator will vary depending upon the
|
||||
implementation for several reasons. Implementations MUST consider
|
||||
whether these possibilities are a problem for their use case:
|
||||
|
||||
1) New characters added in Unicode may have decomposition or
|
||||
titlecase properties that will not be known to an implementation
|
||||
based upon an older revision of Unicode. This impacts step (2).
|
||||
|
||||
2) Step (2)(b) defines a subset of Normalization Form KD (NFKD) that
|
||||
does not require normalization of out-of-order diacriticals.
|
||||
However, an implementation MAY use an NFKD library routine that
|
||||
does such normalization. This impacts step (2)(b) and possibly
|
||||
also step (1)(a), and is an issue only with ill-formed UTF-8
|
||||
input.
|
||||
|
||||
3) The set of charsets handled in step (1)(a) is open-ended. UTF-8
|
||||
(and, by extension, US-ASCII) are the only mandatory-to-implement
|
||||
charsets. This impacts step (1)(a).
|
||||
|
||||
Implementations SHOULD, as far as feasible, support all the
|
||||
charsets they are likely to encounter in the input data, in order
|
||||
to avoid poor collation caused by the fall through to the (1)(b)
|
||||
rule.
|
||||
|
||||
4) Other charsets may have revisions which add new characters that
|
||||
are not known to an implementation based upon an older revision.
|
||||
This impacts step (1)(a) and possibly also step (1)(b).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 4]
|
||||
|
||||
RFC 5051 i;unicode-casemap October 2007
|
||||
|
||||
|
||||
An attacker may create input that is ill-formed or in an unknown
|
||||
charset, with the intention of impacting the results of this
|
||||
comparator or exploiting other parts of the system which process this
|
||||
input in different ways. Note, however, that even well-formed data
|
||||
in a known charset can impact the result of this comparator in
|
||||
unexpected ways. For example, an attacker can substitute U+0041
|
||||
(LATIN CAPITAL LETTER A) with U+0391 (GREEK CAPITAL LETTER ALPHA) or
|
||||
U+0410 (CYRILLIC CAPITAL LETTER A) in the intention of causing a
|
||||
non-match of strings which visually appear the same and/or causing
|
||||
the string to appear elsewhere in a sort.
|
||||
|
||||
5. IANA Considerations
|
||||
|
||||
The i;unicode-casemap collation defined in section 2 has been added
|
||||
to the registry of collations defined in [COMPARATOR].
|
||||
|
||||
6. Normative References
|
||||
|
||||
[COMPARATOR] Newman, C., Duerst, M., and A. Gulbrandsen,
|
||||
"Internet Application Protocol Collation
|
||||
Registry", RFC 4790, February 2007.
|
||||
|
||||
[STRINGPREP] Hoffman, P. and M. Blanchet, "Preparation of
|
||||
Internationalized Strings ("stringprep")", RFC
|
||||
3454, December 2002.
|
||||
|
||||
[UTF-8] Yergeau, F., "UTF-8, a transformation format of
|
||||
ISO 10646", STD 63, RFC 3629, November 2003.
|
||||
|
||||
[UNICODE-DATA] <http://www.unicode.org/Public/UNIDATA/
|
||||
UnicodeData.txt>
|
||||
|
||||
Although the UnicodeData.txt file referenced
|
||||
here is part of the Unicode standard, it is
|
||||
subject to change as new characters are added
|
||||
to Unicode and errors are corrected in Unicode
|
||||
revisions. As a result, it may be less stable
|
||||
than might otherwise be implied by the
|
||||
standards status of this specification.
|
||||
|
||||
[UNICODE-SECURITY] Davis, M. and M. Suignard, "Unicode Security
|
||||
Considerations", February 2006,
|
||||
<http://www.unicode.org/reports/tr36/>.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 5]
|
||||
|
||||
RFC 5051 i;unicode-casemap October 2007
|
||||
|
||||
|
||||
7. Informative References
|
||||
|
||||
[BASIC] Newman, C., Duerst, M., and A. Gulbrandsen,
|
||||
"i;basic - the Unicode Collation Algorithm",
|
||||
Work in Progress, March 2007.
|
||||
|
||||
[IMAP-SORT] Crispin, M. and K. Murchison, "Internet Message
|
||||
Access Protocol - SORT and THREAD Extensions",
|
||||
Work in Progress, September 2007.
|
||||
|
||||
Author's Address
|
||||
|
||||
Mark R. Crispin
|
||||
Networks and Distributed Computing
|
||||
University of Washington
|
||||
4545 15th Avenue NE
|
||||
Seattle, WA 98105-4527
|
||||
|
||||
Phone: +1 (206) 543-5762
|
||||
EMail: MRC@CAC.Washington.EDU
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 6]
|
||||
|
||||
RFC 5051 i;unicode-casemap October 2007
|
||||
|
||||
|
||||
Full Copyright Statement
|
||||
|
||||
Copyright (C) The IETF Trust (2007).
|
||||
|
||||
This document is subject to the rights, licenses and restrictions
|
||||
contained in BCP 78, and except as set forth therein, the authors
|
||||
retain all their rights.
|
||||
|
||||
This document and the information contained herein are provided on an
|
||||
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
|
||||
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
|
||||
THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
|
||||
THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
Intellectual Property
|
||||
|
||||
The IETF takes no position regarding the validity or scope of any
|
||||
Intellectual Property Rights or other rights that might be claimed to
|
||||
pertain to the implementation or use of the technology described in
|
||||
this document or the extent to which any license under such rights
|
||||
might or might not be available; nor does it represent that it has
|
||||
made any independent effort to identify any such rights. Information
|
||||
on the procedures with respect to rights in RFC documents can be
|
||||
found in BCP 78 and BCP 79.
|
||||
|
||||
Copies of IPR disclosures made to the IETF Secretariat and any
|
||||
assurances of licenses to be made available, or the result of an
|
||||
attempt made to obtain a general license or permission for the use of
|
||||
such proprietary rights by implementers or users of this
|
||||
specification can be obtained from the IETF on-line IPR repository at
|
||||
http://www.ietf.org/ipr.
|
||||
|
||||
The IETF invites any interested party to bring to its attention any
|
||||
copyrights, patents or patent applications, or other proprietary
|
||||
rights that may cover technology that may be required to implement
|
||||
this standard. Please address the information to the IETF at
|
||||
ietf-ipr@ietf.org.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Crispin Standards Track [Page 7]
|
||||
|
281
vendor/sabre/dav/docs/rfc5397.txt
vendored
Normal file
281
vendor/sabre/dav/docs/rfc5397.txt
vendored
Normal file
@ -0,0 +1,281 @@
|
||||
|
||||
|
||||
|
||||
Network Working Group W. Sanchez
|
||||
Request for Comments: 5397 C. Daboo
|
||||
Category: Standards Track Apple Inc.
|
||||
December 2008
|
||||
|
||||
|
||||
WebDAV Current Principal Extension
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This document specifies an Internet standards track protocol for the
|
||||
Internet community, and requests discussion and suggestions for
|
||||
improvements. Please refer to the current edition of the "Internet
|
||||
Official Protocol Standards" (STD 1) for the standardization state
|
||||
and status of this protocol. Distribution of this memo is unlimited.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2008 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document.
|
||||
|
||||
Abstract
|
||||
|
||||
This specification defines a new WebDAV property that allows clients
|
||||
to quickly determine the principal corresponding to the current
|
||||
authenticated user.
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
|
||||
2. Conventions Used in This Document . . . . . . . . . . . . . . . 2
|
||||
3. DAV:current-user-principal . . . . . . . . . . . . . . . . . . 3
|
||||
4. Security Considerations . . . . . . . . . . . . . . . . . . . . 4
|
||||
5. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . 4
|
||||
6. Normative References . . . . . . . . . . . . . . . . . . . . . 4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sanchez & Daboo Standards Track [Page 1]
|
||||
|
||||
RFC 5397 WebDAV Current Principal December 2008
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
WebDAV [RFC4918] is an extension to HTTP [RFC2616] to support
|
||||
improved document authoring capabilities. The WebDAV Access Control
|
||||
Protocol ("WebDAV ACL") [RFC3744] extension adds access control
|
||||
capabilities to WebDAV. It introduces the concept of a "principal"
|
||||
resource, which is used to represent information about authenticated
|
||||
entities on the system.
|
||||
|
||||
Some clients have a need to determine which [RFC3744] principal a
|
||||
server is associating with the currently authenticated HTTP user.
|
||||
While [RFC3744] defines a DAV:current-user-privilege-set property for
|
||||
retrieving the privileges granted to that principal, there is no
|
||||
recommended way to identify the principal in question, which is
|
||||
necessary to perform other useful operations. For example, a client
|
||||
may wish to determine which groups the current user is a member of,
|
||||
or modify a property of the principal resource associated with the
|
||||
current user.
|
||||
|
||||
The DAV:principal-match REPORT provides some useful functionality,
|
||||
but there are common situations where the results from that query can
|
||||
be ambiguous. For example, not only is an individual user principal
|
||||
returned, but also every group principal that the user is a member
|
||||
of, and there is no clear way to distinguish which is which.
|
||||
|
||||
This specification proposes an extension to WebDAV ACL that adds a
|
||||
DAV:current-user-principal property to resources under access control
|
||||
on the server. This property provides a URL to a principal resource
|
||||
corresponding to the currently authenticated user. This allows a
|
||||
client to "bootstrap" itself by performing additional queries on the
|
||||
principal resource to obtain additional information from that
|
||||
resource, which is the purpose of this extension. Note that while it
|
||||
is possible for multiple URLs to refer to the same principal
|
||||
resource, or for multiple principal resources to correspond to a
|
||||
single principal, this specification only allows for a single http(s)
|
||||
URL in the DAV:current-user-principal property. If a client wishes
|
||||
to obtain alternate URLs for the principal, it can query the
|
||||
principal resource for this information; it is not the purpose of
|
||||
this extension to provide a complete list of such URLs, but simply to
|
||||
provide a means to locate a resource which contains that (and other)
|
||||
information.
|
||||
|
||||
2. Conventions Used in This Document
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
|
||||
|
||||
|
||||
Sanchez & Daboo Standards Track [Page 2]
|
||||
|
||||
RFC 5397 WebDAV Current Principal December 2008
|
||||
|
||||
|
||||
When XML element types in the namespace "DAV:" are referenced in this
|
||||
document outside of the context of an XML fragment, the string "DAV:"
|
||||
will be prefixed to the element type names.
|
||||
|
||||
Processing of XML by clients and servers MUST follow the rules
|
||||
defined in Section 17 of WebDAV [RFC4918].
|
||||
|
||||
Some of the declarations refer to XML elements defined by WebDAV
|
||||
[RFC4918].
|
||||
|
||||
3. DAV:current-user-principal
|
||||
|
||||
Name: current-user-principal
|
||||
|
||||
Namespace: DAV:
|
||||
|
||||
Purpose: Indicates a URL for the currently authenticated user's
|
||||
principal resource on the server.
|
||||
|
||||
Value: A single DAV:href or DAV:unauthenticated element.
|
||||
|
||||
Protected: This property is computed on a per-request basis, and
|
||||
therefore is protected.
|
||||
|
||||
Description: The DAV:current-user-principal property contains either
|
||||
a DAV:href or DAV:unauthenticated XML element. The DAV:href
|
||||
element contains a URL to a principal resource corresponding to
|
||||
the currently authenticated user. That URL MUST be one of the
|
||||
URLs in the DAV:principal-URL or DAV:alternate-URI-set properties
|
||||
defined on the principal resource and MUST be an http(s) scheme
|
||||
URL. When authentication has not been done or has failed, this
|
||||
property MUST contain the DAV:unauthenticated pseudo-principal.
|
||||
|
||||
In some cases, there may be multiple principal resources
|
||||
corresponding to the same authenticated principal. In that case,
|
||||
the server is free to choose any one of the principal resource
|
||||
URIs for the value of the DAV:current-user-principal property.
|
||||
However, servers SHOULD be consistent and use the same principal
|
||||
resource URI for each authenticated principal.
|
||||
|
||||
COPY/MOVE behavior: This property is computed on a per-request
|
||||
basis, and is thus never copied or moved.
|
||||
|
||||
Definition:
|
||||
|
||||
<!ELEMENT current-user-principal (unauthenticated | href)>
|
||||
<!-- href value: a URL to a principal resource -->
|
||||
|
||||
|
||||
|
||||
|
||||
Sanchez & Daboo Standards Track [Page 3]
|
||||
|
||||
RFC 5397 WebDAV Current Principal December 2008
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
<D:current-user-principal xmlns:D="DAV:">
|
||||
<D:href>/principals/users/cdaboo</D:href>
|
||||
</D:current-user-principal>
|
||||
|
||||
4. Security Considerations
|
||||
|
||||
This specification does not introduce any additional security issues
|
||||
beyond those defined for HTTP [RFC2616], WebDAV [RFC4918], and WebDAV
|
||||
ACL [RFC3744].
|
||||
|
||||
5. Acknowledgments
|
||||
|
||||
This specification is based on discussions that took place within the
|
||||
Calendaring and Scheduling Consortium's CalDAV Technical Committee.
|
||||
The authors thank the participants of that group for their input.
|
||||
|
||||
The authors thank Julian Reschke for his valuable input via the
|
||||
WebDAV working group mailing list.
|
||||
|
||||
6. Normative References
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
|
||||
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
|
||||
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
|
||||
|
||||
[RFC3744] Clemm, G., Reschke, J., Sedlar, E., and J. Whitehead, "Web
|
||||
Distributed Authoring and Versioning (WebDAV)
|
||||
Access Control Protocol", RFC 3744, May 2004.
|
||||
|
||||
[RFC4918] Dusseault, L., "HTTP Extensions for Web Distributed
|
||||
Authoring and Versioning (WebDAV)", RFC 4918, June 2007.
|
||||
|
||||
Authors' Addresses
|
||||
|
||||
Wilfredo Sanchez
|
||||
Apple Inc.
|
||||
1 Infinite Loop
|
||||
Cupertino, CA 95014
|
||||
USA
|
||||
|
||||
EMail: wsanchez@wsanchez.net
|
||||
URI: http://www.apple.com/
|
||||
|
||||
|
||||
|
||||
|
||||
Sanchez & Daboo Standards Track [Page 4]
|
||||
|
||||
RFC 5397 WebDAV Current Principal December 2008
|
||||
|
||||
|
||||
Cyrus Daboo
|
||||
Apple Inc.
|
||||
1 Infinite Loop
|
||||
Cupertino, CA 95014
|
||||
USA
|
||||
|
||||
EMail: cyrus@daboo.name
|
||||
URI: http://www.apple.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Sanchez & Daboo Standards Track [Page 5]
|
||||
|
||||
|
9411
vendor/sabre/dav/docs/rfc5545.txt
vendored
Normal file
9411
vendor/sabre/dav/docs/rfc5545.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7451
vendor/sabre/dav/docs/rfc5546.txt
vendored
Normal file
7451
vendor/sabre/dav/docs/rfc5546.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
675
vendor/sabre/dav/docs/rfc5689.txt
vendored
Normal file
675
vendor/sabre/dav/docs/rfc5689.txt
vendored
Normal file
@ -0,0 +1,675 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Network Working Group C. Daboo
|
||||
Request for Comments: 5689 Apple Inc.
|
||||
Updates: 4791, 4918 September 2009
|
||||
Category: Standards Track
|
||||
|
||||
|
||||
Extended MKCOL for Web Distributed Authoring and Versioning (WebDAV)
|
||||
|
||||
Abstract
|
||||
|
||||
This specification extends the Web Distributed Authoring and
|
||||
Versioning (WebDAV) MKCOL (Make Collection) method to allow
|
||||
collections of arbitrary resourcetype to be created and to allow
|
||||
properties to be set at the same time.
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This document specifies an Internet standards track protocol for the
|
||||
Internet community, and requests discussion and suggestions for
|
||||
improvements. Please refer to the current edition of the "Internet
|
||||
Official Protocol Standards" (STD 1) for the standardization state
|
||||
and status of this protocol. Distribution of this memo is unlimited.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2009 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document. Code Components extracted from this document must
|
||||
include Simplified BSD License text as described in Section 4.e of
|
||||
the Trust Legal Provisions and are provided without warranty as
|
||||
described in the BSD License.
|
||||
|
||||
This document may contain material from IETF Documents or IETF
|
||||
Contributions published or made publicly available before November
|
||||
10, 2008. The person(s) controlling the copyright in some of this
|
||||
material may not have granted the IETF Trust the right to allow
|
||||
modifications of such material outside the IETF Standards Process.
|
||||
Without obtaining an adequate license from the person(s) controlling
|
||||
the copyright in such materials, this document may not be modified
|
||||
outside the IETF Standards Process, and derivative works of it may
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 1]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
not be created outside the IETF Standards Process, except to format
|
||||
it for publication as an RFC or to translate it into languages other
|
||||
than English.
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
2. Conventions Used in This Document . . . . . . . . . . . . . . 3
|
||||
3. WebDAV Extended MKCOL . . . . . . . . . . . . . . . . . . . . 4
|
||||
3.1. Extended MKCOL Support . . . . . . . . . . . . . . . . . . 5
|
||||
3.1.1. Example: Using OPTIONS for the Discovery of
|
||||
Support for Extended MKCOL . . . . . . . . . . . . . . 5
|
||||
3.2. Status Codes . . . . . . . . . . . . . . . . . . . . . . . 5
|
||||
3.3. Additional Precondition for Extended MKCOL . . . . . . . . 5
|
||||
3.4. Example: Successful Extended MKCOL Request . . . . . . . . 6
|
||||
3.5. Example: Unsuccessful Extended MKCOL Request . . . . . . . 6
|
||||
4. Using Extended MKCOL as an Alternative for MKxxx Methods . . . 8
|
||||
4.1. MKCALENDAR Alternative . . . . . . . . . . . . . . . . . . 8
|
||||
4.1.1. Example: Using MKCOL Instead of MKCALENDAR . . . . . . 8
|
||||
5. XML Element Definitions . . . . . . . . . . . . . . . . . . . 10
|
||||
5.1. mkcol XML Element . . . . . . . . . . . . . . . . . . . . 10
|
||||
5.2. mkcol-response XML Element . . . . . . . . . . . . . . . . 10
|
||||
6. Security Considerations . . . . . . . . . . . . . . . . . . . 11
|
||||
7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 11
|
||||
8. Normative References . . . . . . . . . . . . . . . . . . . . . 11
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 2]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
1. Introduction
|
||||
|
||||
WebDAV [RFC4918] defines the HTTP [RFC2616] method MKCOL. This
|
||||
method is used to create WebDAV collections on the server. However,
|
||||
several WebDAV-based specifications (e.g., CalDAV [RFC4791]) define
|
||||
"special" collections -- ones that are identified by additional
|
||||
values in the DAV:resourcetype property assigned to the collection
|
||||
resource or by other means. These "special" collections are created
|
||||
by new methods (e.g., MKCALENDAR). The addition of a new MKxxx
|
||||
method for each new "special" collection adds to server complexity
|
||||
and is detrimental to overall reliability due to the need to make
|
||||
sure intermediaries are aware of these methods.
|
||||
|
||||
This specification defines an extension to the WebDAV MKCOL method
|
||||
that adds a request body allowing a client to specify WebDAV
|
||||
properties to be set on the newly created collection or resource. In
|
||||
particular, the DAV:resourcetype property can be used to create a
|
||||
"special" collection; alternatively, other properties can be used to
|
||||
create a "special" resource. This avoids the need to invent new
|
||||
MKxxx methods.
|
||||
|
||||
2. Conventions Used in This Document
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in [RFC2119].
|
||||
|
||||
This document uses XML DTD fragments (Section 3.2 of
|
||||
[W3C.REC-xml-20081126]) as a purely notational convention. WebDAV
|
||||
request and response bodies cannot be validated by a DTD due to the
|
||||
specific extensibility rules defined in Section 17 of [RFC4918] and
|
||||
due to the fact that all XML elements defined by this specification
|
||||
use the XML namespace name "DAV:". In particular:
|
||||
|
||||
1. Element names use the "DAV:" namespace.
|
||||
|
||||
2. Element ordering is irrelevant unless explicitly stated.
|
||||
|
||||
3. Extension elements (elements not already defined as valid child
|
||||
elements) may be added anywhere, except when explicitly stated
|
||||
otherwise.
|
||||
|
||||
4. Extension attributes (attributes not already defined as valid for
|
||||
this element) may be added anywhere, except when explicitly
|
||||
stated otherwise.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 3]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
When an XML element type in the "DAV:" namespace is referenced in
|
||||
this document outside of the context of an XML fragment, the string
|
||||
"DAV:" will be prefixed to the element type.
|
||||
|
||||
This document inherits, and sometimes extends, DTD productions from
|
||||
Section 14 of [RFC4918].
|
||||
|
||||
3. WebDAV Extended MKCOL
|
||||
|
||||
The WebDAV MKCOL request is extended to allow the inclusion of a
|
||||
request body. The request body is an XML document containing a
|
||||
single DAV:mkcol XML element as the root element. The Content-Type
|
||||
request header MUST be set appropriately for an XML body (e.g., set
|
||||
to "text/xml" or "application/xml"). XML-typed bodies for an MKCOL
|
||||
request that do not have DAV:mkcol as the root element are reserved
|
||||
for future usage.
|
||||
|
||||
One or more DAV:set XML elements may be included in the DAV:mkcol XML
|
||||
element to allow setting properties on the collection as it is
|
||||
created. In particular, to create a collection of a particular type,
|
||||
the DAV:resourcetype XML element MUST be included in a DAV:set XML
|
||||
element and MUST specify the expected resource type elements for the
|
||||
new resource, which MUST include the DAV:collection element that
|
||||
needs to be present for any WebDAV collection.
|
||||
|
||||
As per the PROPPATCH method (Section 9.2 of [RFC4918]), servers MUST
|
||||
process any DAV:set instructions in document order (an exception to
|
||||
the normal rule that ordering is irrelevant). If any one instruction
|
||||
fails to execute successfully, all instructions MUST fail (i.e.,
|
||||
either all succeed or all fail). Thus, if any error occurs during
|
||||
processing, all executed instructions MUST be undone and a proper
|
||||
error result returned. Failure to set a property value on the
|
||||
collection MUST result in a failure of the overall MKCOL request --
|
||||
i.e., the collection is not created.
|
||||
|
||||
The response to an extended MKCOL request MUST be an XML document
|
||||
containing a single DAV:mkcol-response XML element, which MUST
|
||||
contain DAV:propstat XML elements with the status of each property
|
||||
when the request fails due to a failure to set one or more of the
|
||||
properties specified in the request body. The server MAY return a
|
||||
response body in the case where the request is successful, indicating
|
||||
success for setting each property specified in the request body.
|
||||
When an empty response body is returned with a success request status
|
||||
code, the client can assume that all properties were set.
|
||||
|
||||
In all other respects, the behavior of the extended MKCOL request
|
||||
follows that of the standard MKCOL request.
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 4]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
3.1. Extended MKCOL Support
|
||||
|
||||
A server supporting the features described in this document MUST
|
||||
include "extended-mkcol" as a field in the DAV response header from
|
||||
an OPTIONS request on any URI that supports use of the extended MKCOL
|
||||
method.
|
||||
|
||||
3.1.1. Example: Using OPTIONS for the Discovery of Support for Extended
|
||||
MKCOL
|
||||
|
||||
>> Request <<
|
||||
|
||||
OPTIONS /addressbooks/users/ HTTP/1.1
|
||||
Host: addressbook.example.com
|
||||
|
||||
>> Response <<
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Allow: OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE
|
||||
Allow: MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, REPORT, ACL
|
||||
DAV: 1, 2, 3, access-control, extended-mkcol
|
||||
Date: Sat, 11 Nov 2006 09:32:12 GMT
|
||||
Content-Length: 0
|
||||
|
||||
3.2. Status Codes
|
||||
|
||||
As per Section 9.3.1 of [RFC4918].
|
||||
|
||||
3.3. Additional Precondition for Extended MKCOL
|
||||
|
||||
WebDAV ([RFC4918], Section 16) defines preconditions and
|
||||
postconditions for request behavior. This specification adds the
|
||||
following precondition for the extended MKCOL request.
|
||||
|
||||
Name: valid-resourcetype
|
||||
|
||||
Namespace: DAV:
|
||||
|
||||
Use with: Typically 403 (Forbidden)
|
||||
|
||||
Purpose: (precondition) -- The server MUST support the specified
|
||||
resourcetype value for the specified collection.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 5]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
3.4. Example: Successful Extended MKCOL Request
|
||||
|
||||
This example shows how the extended MKCOL request is used to create a
|
||||
collection of a fictitious type "special-resource". The response
|
||||
body is empty as the request completed successfully.
|
||||
|
||||
>> Request <<
|
||||
|
||||
MKCOL /home/special/ HTTP/1.1
|
||||
Host: special.example.com
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:mkcol xmlns:D="DAV:"
|
||||
xmlns:E="http://example.com/ns/">
|
||||
<D:set>
|
||||
<D:prop>
|
||||
<D:resourcetype>
|
||||
<D:collection/>
|
||||
<E:special-resource/>
|
||||
</D:resourcetype>
|
||||
<D:displayname>Special Resource</D:displayname>
|
||||
</D:prop>
|
||||
</D:set>
|
||||
</D:mkcol>
|
||||
|
||||
>> Response <<
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Cache-Control: no-cache
|
||||
Date: Sat, 11 Nov 2006 09:32:12 GMT
|
||||
|
||||
3.5. Example: Unsuccessful Extended MKCOL Request
|
||||
|
||||
This example shows an attempt to use the extended MKCOL request to
|
||||
create a collection of a fictitious type "special-resource", which is
|
||||
not actually supported by the server. The response body shows that
|
||||
an error occurred specifically with the DAV:resourcetype property.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 6]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
>> Request <<
|
||||
|
||||
MKCOL /home/special/ HTTP/1.1
|
||||
Host: special.example.com
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:mkcol xmlns:D="DAV:"
|
||||
xmlns:E="http://example.com/ns/">
|
||||
<D:set>
|
||||
<D:prop>
|
||||
<D:resourcetype>
|
||||
<D:collection/>
|
||||
<E:special-resource/>
|
||||
</D:resourcetype>
|
||||
<D:displayname>Special Resource</D:displayname>
|
||||
</D:prop>
|
||||
</D:set>
|
||||
</D:mkcol>
|
||||
|
||||
>> Response <<
|
||||
|
||||
HTTP/1.1 403 Forbidden
|
||||
Cache-Control: no-cache
|
||||
Date: Sat, 11 Nov 2006 09:32:12 GMT
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:mkcol-response xmlns:D="DAV:">
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 403 Forbidden</D:status>
|
||||
<D:error><D:valid-resourcetype /></D:error>
|
||||
<D:responsedescription>Resource type is not
|
||||
supported by this server</D:responsedescription>
|
||||
</D:propstat>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:displayname/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 424 Failed Dependency</D:status>
|
||||
</D:propstat>
|
||||
</D:mkcol-response>
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 7]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
4. Using Extended MKCOL as an Alternative for MKxxx Methods
|
||||
|
||||
One of the goals of this extension is to eliminate the need for other
|
||||
extensions to define their own variant of MKCOL to create the special
|
||||
collections they need. This extension can be used as an alternative
|
||||
to existing MKxxx methods in other extensions as detailed below. If
|
||||
a server supports this extension and the other extension listed, then
|
||||
the server MUST support use of the extended MKCOL method to achieve
|
||||
the same result as the MKxxx method of the other extension.
|
||||
|
||||
4.1. MKCALENDAR Alternative
|
||||
|
||||
CalDAV defines the MKCALENDAR method to create a calendar collection
|
||||
as well as to set properties during creation (Section 5.3.1 of
|
||||
[RFC4791]).
|
||||
|
||||
The extended MKCOL method can be used instead by specifying both DAV:
|
||||
collection and CALDAV:calendar-collection XML elements in the DAV:
|
||||
resourcetype property, set during the extended MKCOL request.
|
||||
|
||||
4.1.1. Example: Using MKCOL Instead of MKCALENDAR
|
||||
|
||||
The first example below shows an MKCALENDAR request containing a
|
||||
CALDAV:mkcalendar XML element in the request body and returning a
|
||||
CALDAV:mkcalendar-response XML element in the response body.
|
||||
|
||||
>> MKCALENDAR Request <<
|
||||
|
||||
MKCALENDAR /home/lisa/calendars/events/ HTTP/1.1
|
||||
Host: calendar.example.com
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<C:mkcalendar xmlns:D="DAV:"
|
||||
xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
<D:set>
|
||||
<D:prop>
|
||||
<D:displayname>Lisa's Events</D:displayname>
|
||||
</D:prop>
|
||||
</D:set>
|
||||
</C:mkcalendar>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 8]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
>> MKCALENDAR Response <<
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Cache-Control: no-cache
|
||||
Date: Sat, 11 Nov 2006 09:32:12 GMT
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<C:mkcalendar-response xmlns:D="DAV:"
|
||||
xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:displayname/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</C:mkcalendar-response>
|
||||
|
||||
The second example shows the equivalent extended MKCOL request with
|
||||
the same request and response XML elements.
|
||||
|
||||
>> MKCOL Request <<
|
||||
|
||||
MKCOL /home/lisa/calendars/events/ HTTP/1.1
|
||||
Host: calendar.example.com
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:mkcol xmlns:D="DAV:"
|
||||
xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
<D:set>
|
||||
<D:prop>
|
||||
<D:resourcetype>
|
||||
<D:collection/>
|
||||
<C:calendar/>
|
||||
</D:resourcetype>
|
||||
<D:displayname>Lisa's Events</D:displayname>
|
||||
</D:prop>
|
||||
</D:set>
|
||||
</D:mkcol>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 9]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
>> MKCOL Response <<
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Cache-Control: no-cache
|
||||
Date: Sat, 11 Nov 2006 09:32:12 GMT
|
||||
Content-Type: application/xml; charset="utf-8"
|
||||
Content-Length: xxxx
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<D:mkcol-response xmlns:D="DAV:"
|
||||
xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<D:resourcetype/>
|
||||
<D:displayname/>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:mkcol-response>
|
||||
|
||||
5. XML Element Definitions
|
||||
|
||||
5.1. mkcol XML Element
|
||||
|
||||
Name: mkcol
|
||||
|
||||
Namespace: DAV:
|
||||
|
||||
Purpose: Used in a request to specify properties to be set in an
|
||||
extended MKCOL request, as well as any additional information
|
||||
needed when creating the resource.
|
||||
|
||||
Description: This XML element is a container for the information
|
||||
required to modify the properties on a collection resource as it
|
||||
is created in an extended MKCOL request.
|
||||
|
||||
Definition:
|
||||
|
||||
<!ELEMENT mkcol (set+)>
|
||||
|
||||
5.2. mkcol-response XML Element
|
||||
|
||||
Name: mkcol-response
|
||||
|
||||
Namespace: DAV:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 10]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
Purpose: Used in a response to indicate the status of properties
|
||||
that were set or failed to be set during an extended MKCOL
|
||||
request.
|
||||
|
||||
Description: This XML element is a container for the information
|
||||
returned about a resource that has been created in an extended
|
||||
MKCOL request.
|
||||
|
||||
Definition:
|
||||
|
||||
<!ELEMENT mkcol-response (propstat+)>
|
||||
|
||||
6. Security Considerations
|
||||
|
||||
This extension does not introduce any new security concerns beyond
|
||||
those already described in HTTP [RFC2616] and WebDAV [RFC4918].
|
||||
|
||||
7. Acknowledgments
|
||||
|
||||
Thanks to Bernard Desruisseaux, Mike Douglass, Alexey Melnikov,
|
||||
Julian Reschke, and Simon Vaillancourt.
|
||||
|
||||
|
||||
8. Normative References
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
|
||||
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
|
||||
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
|
||||
|
||||
[RFC4791] Daboo, C., Desruisseaux, B., and L. Dusseault,
|
||||
"Calendaring Extensions to WebDAV (CalDAV)", RFC 4791,
|
||||
March 2007.
|
||||
|
||||
[RFC4918] Dusseault, L., "HTTP Extensions for Web Distributed
|
||||
Authoring and Versioning (WebDAV)", RFC 4918, June 2007.
|
||||
|
||||
[W3C.REC-xml-20081126]
|
||||
Maler, E., Yergeau, F., Paoli, J., Bray, T., and C.
|
||||
Sperberg-McQueen, "Extensible Markup Language (XML) 1.0
|
||||
(Fifth Edition)", World Wide Web Consortium
|
||||
Recommendation REC-xml-20081126, November 2008,
|
||||
<http://www.w3.org/TR/2008/REC-xml-20081126>.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 11]
|
||||
|
||||
RFC 5689 Extended MKCOL for WebDAV September 2009
|
||||
|
||||
|
||||
Author's Address
|
||||
|
||||
Cyrus Daboo
|
||||
Apple Inc.
|
||||
1 Infinite Loop
|
||||
Cupertino, CA 95014
|
||||
USA
|
||||
|
||||
EMail: cyrus@daboo.name
|
||||
URI: http://www.apple.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Daboo Standards Track [Page 12]
|
||||
|
451
vendor/sabre/dav/docs/rfc5785.txt
vendored
Normal file
451
vendor/sabre/dav/docs/rfc5785.txt
vendored
Normal file
@ -0,0 +1,451 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Internet Engineering Task Force (IETF) M. Nottingham
|
||||
Request for Comments: 5785 E. Hammer-Lahav
|
||||
Updates: 2616, 2818 April 2010
|
||||
Category: Standards Track
|
||||
ISSN: 2070-1721
|
||||
|
||||
|
||||
Defining Well-Known Uniform Resource Identifiers (URIs)
|
||||
|
||||
Abstract
|
||||
|
||||
This memo defines a path prefix for "well-known locations",
|
||||
"/.well-known/", in selected Uniform Resource Identifier (URI)
|
||||
schemes.
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This is an Internet Standards Track document.
|
||||
|
||||
This document is a product of the Internet Engineering Task Force
|
||||
(IETF). It represents the consensus of the IETF community. It has
|
||||
received public review and has been approved for publication by the
|
||||
Internet Engineering Steering Group (IESG). Further information on
|
||||
Internet Standards is available in Section 2 of RFC 5741.
|
||||
|
||||
Information about the current status of this document, any errata,
|
||||
and how to provide feedback on it may be obtained at
|
||||
http://www.rfc-editor.org/info/rfc5785.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2010 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document. Code Components extracted from this document must
|
||||
include Simplified BSD License text as described in Section 4.e of
|
||||
the Trust Legal Provisions and are provided without warranty as
|
||||
described in the Simplified BSD License.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 1]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
|
||||
1.1. Appropriate Use of Well-Known URIs . . . . . . . . . . . . 3
|
||||
2. Notational Conventions . . . . . . . . . . . . . . . . . . . . 3
|
||||
3. Well-Known URIs . . . . . . . . . . . . . . . . . . . . . . . . 3
|
||||
4. Security Considerations . . . . . . . . . . . . . . . . . . . . 4
|
||||
5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 4
|
||||
5.1. The Well-Known URI Registry . . . . . . . . . . . . . . . . 4
|
||||
5.1.1. Registration Template . . . . . . . . . . . . . . . . . 5
|
||||
6. References . . . . . . . . . . . . . . . . . . . . . . . . . . 5
|
||||
6.1. Normative References . . . . . . . . . . . . . . . . . . . 5
|
||||
6.2. Informative References . . . . . . . . . . . . . . . . . . 5
|
||||
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . . 7
|
||||
Appendix B. Frequently Asked Questions . . . . . . . . . . . . . . 7
|
||||
|
||||
1. Introduction
|
||||
|
||||
It is increasingly common for Web-based protocols to require the
|
||||
discovery of policy or other information about a host ("site-wide
|
||||
metadata") before making a request. For example, the Robots
|
||||
Exclusion Protocol <http://www.robotstxt.org/> specifies a way for
|
||||
automated processes to obtain permission to access resources;
|
||||
likewise, the Platform for Privacy Preferences [W3C.REC-P3P-20020416]
|
||||
tells user-agents how to discover privacy policy beforehand.
|
||||
|
||||
While there are several ways to access per-resource metadata (e.g.,
|
||||
HTTP headers, WebDAV's PROPFIND [RFC4918]), the perceived overhead
|
||||
(either in terms of client-perceived latency and/or deployment
|
||||
difficulties) associated with them often precludes their use in these
|
||||
scenarios.
|
||||
|
||||
When this happens, it is common to designate a "well-known location"
|
||||
for such data, so that it can be easily located. However, this
|
||||
approach has the drawback of risking collisions, both with other such
|
||||
designated "well-known locations" and with pre-existing resources.
|
||||
|
||||
To address this, this memo defines a path prefix in HTTP(S) URIs for
|
||||
these "well-known locations", "/.well-known/". Future specifications
|
||||
that need to define a resource for such site-wide metadata can
|
||||
register their use to avoid collisions and minimise impingement upon
|
||||
sites' URI space.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 2]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
1.1. Appropriate Use of Well-Known URIs
|
||||
|
||||
There are a number of possible ways that applications could use Well-
|
||||
known URIs. However, in keeping with the Architecture of the World-
|
||||
Wide Web [W3C.REC-webarch-20041215], well-known URIs are not intended
|
||||
for general information retrieval or establishment of large URI
|
||||
namespaces on the Web. Rather, they are designed to facilitate
|
||||
discovery of information on a site when it isn't practical to use
|
||||
other mechanisms; for example, when discovering policy that needs to
|
||||
be evaluated before a resource is accessed, or when using multiple
|
||||
round-trips is judged detrimental to performance.
|
||||
|
||||
As such, the well-known URI space was created with the expectation
|
||||
that it will be used to make site-wide policy information and other
|
||||
metadata available directly (if sufficiently concise), or provide
|
||||
references to other URIs that provide such metadata.
|
||||
|
||||
2. Notational Conventions
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in RFC 2119 [RFC2119].
|
||||
|
||||
3. Well-Known URIs
|
||||
|
||||
A well-known URI is a URI [RFC3986] whose path component begins with
|
||||
the characters "/.well-known/", and whose scheme is "HTTP", "HTTPS",
|
||||
or another scheme that has explicitly been specified to use well-
|
||||
known URIs.
|
||||
|
||||
Applications that wish to mint new well-known URIs MUST register
|
||||
them, following the procedures in Section 5.1.
|
||||
|
||||
For example, if an application registers the name 'example', the
|
||||
corresponding well-known URI on 'http://www.example.com/' would be
|
||||
'http://www.example.com/.well-known/example'.
|
||||
|
||||
Registered names MUST conform to the segment-nz production in
|
||||
[RFC3986].
|
||||
|
||||
Note that this specification defines neither how to determine the
|
||||
authority to use for a particular context, nor the scope of the
|
||||
metadata discovered by dereferencing the well-known URI; both should
|
||||
be defined by the application itself.
|
||||
|
||||
Typically, a registration will reference a specification that defines
|
||||
the format and associated media type to be obtained by dereferencing
|
||||
the well-known URI.
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 3]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
It MAY also contain additional information, such as the syntax of
|
||||
additional path components, query strings and/or fragment identifiers
|
||||
to be appended to the well-known URI, or protocol-specific details
|
||||
(e.g., HTTP [RFC2616] method handling).
|
||||
|
||||
Note that this specification does not define a format or media-type
|
||||
for the resource located at "/.well-known/" and clients should not
|
||||
expect a resource to exist at that location.
|
||||
|
||||
4. Security Considerations
|
||||
|
||||
This memo does not specify the scope of applicability of metadata or
|
||||
policy obtained from a well-known URI, and does not specify how to
|
||||
discover a well-known URI for a particular application. Individual
|
||||
applications using this mechanism must define both aspects.
|
||||
|
||||
Applications minting new well-known URIs, as well as administrators
|
||||
deploying them, will need to consider several security-related
|
||||
issues, including (but not limited to) exposure of sensitive data,
|
||||
denial-of-service attacks (in addition to normal load issues), server
|
||||
and client authentication, vulnerability to DNS rebinding attacks,
|
||||
and attacks where limited access to a server grants the ability to
|
||||
affect how well-known URIs are served.
|
||||
|
||||
5. IANA Considerations
|
||||
|
||||
5.1. The Well-Known URI Registry
|
||||
|
||||
This document establishes the well-known URI registry.
|
||||
|
||||
Well-known URIs are registered on the advice of one or more
|
||||
Designated Experts (appointed by the IESG or their delegate), with a
|
||||
Specification Required (using terminology from [RFC5226]). However,
|
||||
to allow for the allocation of values prior to publication, the
|
||||
Designated Expert(s) may approve registration once they are satisfied
|
||||
that such a specification will be published.
|
||||
|
||||
Registration requests should be sent to the
|
||||
wellknown-uri-review@ietf.org mailing list for review and comment,
|
||||
with an appropriate subject (e.g., "Request for well-known URI:
|
||||
example").
|
||||
|
||||
Before a period of 14 days has passed, the Designated Expert(s) will
|
||||
either approve or deny the registration request, communicating this
|
||||
decision both to the review list and to IANA. Denials should include
|
||||
an explanation and, if applicable, suggestions as to how to make the
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 4]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
request successful. Registration requests that are undetermined for
|
||||
a period longer than 21 days can be brought to the IESG's attention
|
||||
(using the iesg@iesg.org mailing list) for resolution.
|
||||
|
||||
5.1.1. Registration Template
|
||||
|
||||
URI suffix: The name requested for the well-known URI, relative to
|
||||
"/.well-known/"; e.g., "example".
|
||||
|
||||
Change controller: For Standards-Track RFCs, state "IETF". For
|
||||
others, give the name of the responsible party. Other details
|
||||
(e.g., postal address, e-mail address, home page URI) may also be
|
||||
included.
|
||||
|
||||
Specification document(s): Reference to the document that specifies
|
||||
the field, preferably including a URI that can be used to retrieve
|
||||
a copy of the document. An indication of the relevant sections
|
||||
may also be included, but is not required.
|
||||
|
||||
Related information: Optionally, citations to additional documents
|
||||
containing further relevant information.
|
||||
|
||||
6. References
|
||||
|
||||
6.1. Normative References
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
|
||||
Resource Identifier (URI): Generic Syntax", STD 66,
|
||||
RFC 3986, January 2005.
|
||||
|
||||
[RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an
|
||||
IANA Considerations Section in RFCs", BCP 26, RFC 5226,
|
||||
May 2008.
|
||||
|
||||
6.2. Informative References
|
||||
|
||||
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter,
|
||||
L., Leach, P., and T. Berners-Lee, "Hypertext Transfer
|
||||
Protocol -- HTTP/1.1", RFC 2616, June 1999.
|
||||
|
||||
[RFC4918] Dusseault, L., "HTTP Extensions for Web Distributed
|
||||
Authoring and Versioning (WebDAV)", RFC 4918, June 2007.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 5]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
[W3C.REC-P3P-20020416]
|
||||
Marchiori, M., "The Platform for Privacy Preferences 1.0
|
||||
(P3P1.0) Specification", World Wide Web Consortium
|
||||
Recommendation REC-P3P-20020416, April 2002,
|
||||
<http://www.w3.org/TR/2002/ REC-P3P-20020416>.
|
||||
|
||||
[W3C.REC-webarch-20041215]
|
||||
Jacobs, I. and N. Walsh, "Architecture of the World Wide
|
||||
Web, Volume One", World Wide Web Consortium
|
||||
Recommendation REC- webarch-20041215, December 2004,
|
||||
<http:// www.w3.org/TR/2004/REC-webarch-20041215>.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 6]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
Appendix A. Acknowledgements
|
||||
|
||||
We would like to acknowledge the contributions of everyone who
|
||||
provided feedback and use cases for this document; in particular,
|
||||
Phil Archer, Dirk Balfanz, Adam Barth, Tim Bray, Brian Eaton, Brad
|
||||
Fitzpatrick, Joe Gregorio, Paul Hoffman, Barry Leiba, Ashok Malhotra,
|
||||
Breno de Medeiros, John Panzer, and Drummond Reed. However, they are
|
||||
not responsible for errors and omissions.
|
||||
|
||||
Appendix B. Frequently Asked Questions
|
||||
|
||||
1. Aren't well-known locations bad for the Web?
|
||||
|
||||
They are, but for various reasons -- both technical and social --
|
||||
they are commonly used and their use is increasing. This memo
|
||||
defines a "sandbox" for them, to reduce the risks of collision and
|
||||
to minimise the impact upon pre-existing URIs on sites.
|
||||
|
||||
2. Why /.well-known?
|
||||
|
||||
It's short, descriptive, and according to search indices, not
|
||||
widely used.
|
||||
|
||||
3. What impact does this have on existing mechanisms, such as P3P and
|
||||
robots.txt?
|
||||
|
||||
None, until they choose to use this mechanism.
|
||||
|
||||
4. Why aren't per-directory well-known locations defined?
|
||||
|
||||
Allowing every URI path segment to have a well-known location
|
||||
(e.g., "/images/.well-known/") would increase the risks of
|
||||
colliding with a pre-existing URI on a site, and generally these
|
||||
solutions are found not to scale well, because they're too
|
||||
"chatty".
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 7]
|
||||
|
||||
RFC 5785 Defining Well-Known URIs April 2010
|
||||
|
||||
|
||||
Authors' Addresses
|
||||
|
||||
Mark Nottingham
|
||||
|
||||
EMail: mnot@mnot.net
|
||||
URI: http://www.mnot.net/
|
||||
|
||||
|
||||
Eran Hammer-Lahav
|
||||
|
||||
EMail: eran@hueniverse.com
|
||||
URI: http://hueniverse.com/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Nottingham & Hammer-Lahav Standards Track [Page 8]
|
||||
|
563
vendor/sabre/dav/docs/rfc5789.txt
vendored
Normal file
563
vendor/sabre/dav/docs/rfc5789.txt
vendored
Normal file
@ -0,0 +1,563 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Internet Engineering Task Force (IETF) L. Dusseault
|
||||
Request for Comments: 5789 Linden Lab
|
||||
Category: Standards Track J. Snell
|
||||
ISSN: 2070-1721 March 2010
|
||||
|
||||
|
||||
PATCH Method for HTTP
|
||||
|
||||
Abstract
|
||||
|
||||
Several applications extending the Hypertext Transfer Protocol (HTTP)
|
||||
require a feature to do partial resource modification. The existing
|
||||
HTTP PUT method only allows a complete replacement of a document.
|
||||
This proposal adds a new HTTP method, PATCH, to modify an existing
|
||||
HTTP resource.
|
||||
|
||||
Status of This Memo
|
||||
|
||||
This is an Internet Standards Track document.
|
||||
|
||||
This document is a product of the Internet Engineering Task Force
|
||||
(IETF). It represents the consensus of the IETF community. It has
|
||||
received public review and has been approved for publication by the
|
||||
Internet Engineering Steering Group (IESG). Further information on
|
||||
Internet Standards is available in Section 2 of RFC 5741.
|
||||
|
||||
Information about the current status of this document, any errata,
|
||||
and how to provide feedback on it may be obtained at
|
||||
http://www.rfc-editor.org/info/rfc5789.
|
||||
|
||||
Copyright Notice
|
||||
|
||||
Copyright (c) 2010 IETF Trust and the persons identified as the
|
||||
document authors. All rights reserved.
|
||||
|
||||
This document is subject to BCP 78 and the IETF Trust's Legal
|
||||
Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info) in effect on the date of
|
||||
publication of this document. Please review these documents
|
||||
carefully, as they describe your rights and restrictions with respect
|
||||
to this document. Code Components extracted from this document must
|
||||
include Simplified BSD License text as described in Section 4.e of
|
||||
the Trust Legal Provisions and are provided without warranty as
|
||||
described in the Simplified BSD License.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 1]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
Table of Contents
|
||||
|
||||
1. Introduction ....................................................2
|
||||
2. The PATCH Method ................................................2
|
||||
2.1. A Simple PATCH Example .....................................4
|
||||
2.2. Error Handling .............................................5
|
||||
3. Advertising Support in OPTIONS ..................................7
|
||||
3.1. The Accept-Patch Header ....................................7
|
||||
3.2. Example OPTIONS Request and Response .......................7
|
||||
4. IANA Considerations .............................................8
|
||||
4.1. The Accept-Patch Response Header ...........................8
|
||||
5. Security Considerations .........................................8
|
||||
6. References ......................................................9
|
||||
6.1. Normative References .......................................9
|
||||
6.2. Informative References .....................................9
|
||||
Appendix A. Acknowledgements .....................................10
|
||||
|
||||
1. Introduction
|
||||
|
||||
This specification defines the new HTTP/1.1 [RFC2616] method, PATCH,
|
||||
which is used to apply partial modifications to a resource.
|
||||
|
||||
A new method is necessary to improve interoperability and prevent
|
||||
errors. The PUT method is already defined to overwrite a resource
|
||||
with a complete new body, and cannot be reused to do partial changes.
|
||||
Otherwise, proxies and caches, and even clients and servers, may get
|
||||
confused as to the result of the operation. POST is already used but
|
||||
without broad interoperability (for one, there is no standard way to
|
||||
discover patch format support). PATCH was mentioned in earlier HTTP
|
||||
specifications, but not completely defined.
|
||||
|
||||
In this document, the key words "MUST", "MUST NOT", "REQUIRED",
|
||||
"SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
|
||||
and "OPTIONAL" are to be interpreted as described in [RFC2119].
|
||||
|
||||
Furthermore, this document uses the ABNF syntax defined in Section
|
||||
2.1 of [RFC2616].
|
||||
|
||||
2. The PATCH Method
|
||||
|
||||
The PATCH method requests that a set of changes described in the
|
||||
request entity be applied to the resource identified by the Request-
|
||||
URI. The set of changes is represented in a format called a "patch
|
||||
document" identified by a media type. If the Request-URI does not
|
||||
point to an existing resource, the server MAY create a new resource,
|
||||
depending on the patch document type (whether it can logically modify
|
||||
a null resource) and permissions, etc.
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 2]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
The difference between the PUT and PATCH requests is reflected in the
|
||||
way the server processes the enclosed entity to modify the resource
|
||||
identified by the Request-URI. In a PUT request, the enclosed entity
|
||||
is considered to be a modified version of the resource stored on the
|
||||
origin server, and the client is requesting that the stored version
|
||||
be replaced. With PATCH, however, the enclosed entity contains a set
|
||||
of instructions describing how a resource currently residing on the
|
||||
origin server should be modified to produce a new version. The PATCH
|
||||
method affects the resource identified by the Request-URI, and it
|
||||
also MAY have side effects on other resources; i.e., new resources
|
||||
may be created, or existing ones modified, by the application of a
|
||||
PATCH.
|
||||
|
||||
PATCH is neither safe nor idempotent as defined by [RFC2616], Section
|
||||
9.1.
|
||||
|
||||
A PATCH request can be issued in such a way as to be idempotent,
|
||||
which also helps prevent bad outcomes from collisions between two
|
||||
PATCH requests on the same resource in a similar time frame.
|
||||
Collisions from multiple PATCH requests may be more dangerous than
|
||||
PUT collisions because some patch formats need to operate from a
|
||||
known base-point or else they will corrupt the resource. Clients
|
||||
using this kind of patch application SHOULD use a conditional request
|
||||
such that the request will fail if the resource has been updated
|
||||
since the client last accessed the resource. For example, the client
|
||||
can use a strong ETag [RFC2616] in an If-Match header on the PATCH
|
||||
request.
|
||||
|
||||
There are also cases where patch formats do not need to operate from
|
||||
a known base-point (e.g., appending text lines to log files, or non-
|
||||
colliding rows to database tables), in which case the same care in
|
||||
client requests is not needed.
|
||||
|
||||
The server MUST apply the entire set of changes atomically and never
|
||||
provide (e.g., in response to a GET during this operation) a
|
||||
partially modified representation. If the entire patch document
|
||||
cannot be successfully applied, then the server MUST NOT apply any of
|
||||
the changes. The determination of what constitutes a successful
|
||||
PATCH can vary depending on the patch document and the type of
|
||||
resource(s) being modified. For example, the common 'diff' utility
|
||||
can generate a patch document that applies to multiple files in a
|
||||
directory hierarchy. The atomicity requirement holds for all
|
||||
directly affected files. See "Error Handling", Section 2.2, for
|
||||
details on status codes and possible error conditions.
|
||||
|
||||
If the request passes through a cache and the Request-URI identifies
|
||||
one or more currently cached entities, those entries SHOULD be
|
||||
treated as stale. A response to this method is only cacheable if it
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 3]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
contains explicit freshness information (such as an Expires header or
|
||||
"Cache-Control: max-age" directive) as well as the Content-Location
|
||||
header matching the Request-URI, indicating that the PATCH response
|
||||
body is a resource representation. A cached PATCH response can only
|
||||
be used to respond to subsequent GET and HEAD requests; it MUST NOT
|
||||
be used to respond to other methods (in particular, PATCH).
|
||||
|
||||
Note that entity-headers contained in the request apply only to the
|
||||
contained patch document and MUST NOT be applied to the resource
|
||||
being modified. Thus, a Content-Language header could be present on
|
||||
the request, but it would only mean (for whatever that's worth) that
|
||||
the patch document had a language. Servers SHOULD NOT store such
|
||||
headers except as trace information, and SHOULD NOT use such header
|
||||
values the same way they might be used on PUT requests. Therefore,
|
||||
this document does not specify a way to modify a document's Content-
|
||||
Type or Content-Language value through headers, though a mechanism
|
||||
could well be designed to achieve this goal through a patch document.
|
||||
|
||||
There is no guarantee that a resource can be modified with PATCH.
|
||||
Further, it is expected that different patch document formats will be
|
||||
appropriate for different types of resources and that no single
|
||||
format will be appropriate for all types of resources. Therefore,
|
||||
there is no single default patch document format that implementations
|
||||
are required to support. Servers MUST ensure that a received patch
|
||||
document is appropriate for the type of resource identified by the
|
||||
Request-URI.
|
||||
|
||||
Clients need to choose when to use PATCH rather than PUT. For
|
||||
example, if the patch document size is larger than the size of the
|
||||
new resource data that would be used in a PUT, then it might make
|
||||
sense to use PUT instead of PATCH. A comparison to POST is even more
|
||||
difficult, because POST is used in widely varying ways and can
|
||||
encompass PUT and PATCH-like operations if the server chooses. If
|
||||
the operation does not modify the resource identified by the Request-
|
||||
URI in a predictable way, POST should be considered instead of PATCH
|
||||
or PUT.
|
||||
|
||||
2.1. A Simple PATCH Example
|
||||
|
||||
PATCH /file.txt HTTP/1.1
|
||||
Host: www.example.com
|
||||
Content-Type: application/example
|
||||
If-Match: "e0023aa4e"
|
||||
Content-Length: 100
|
||||
|
||||
[description of changes]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 4]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
This example illustrates use of a hypothetical patch document on an
|
||||
existing resource.
|
||||
|
||||
Successful PATCH response to existing text file:
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Content-Location: /file.txt
|
||||
ETag: "e0023aa4f"
|
||||
|
||||
The 204 response code is used because the response does not carry a
|
||||
message body (which a response with the 200 code would have). Note
|
||||
that other success codes could be used as well.
|
||||
|
||||
Furthermore, the ETag response header field contains the ETag for the
|
||||
entity created by applying the PATCH, available at
|
||||
http://www.example.com/file.txt, as indicated by the Content-Location
|
||||
response header field.
|
||||
|
||||
2.2. Error Handling
|
||||
|
||||
There are several known conditions under which a PATCH request can
|
||||
fail.
|
||||
|
||||
Malformed patch document: When the server determines that the patch
|
||||
document provided by the client is not properly formatted, it
|
||||
SHOULD return a 400 (Bad Request) response. The definition of
|
||||
badly formatted depends on the patch document chosen.
|
||||
|
||||
Unsupported patch document: Can be specified using a 415
|
||||
(Unsupported Media Type) response when the client sends a patch
|
||||
document format that the server does not support for the resource
|
||||
identified by the Request-URI. Such a response SHOULD include an
|
||||
Accept-Patch response header as described in Section 3.1 to notify
|
||||
the client what patch document media types are supported.
|
||||
|
||||
Unprocessable request: Can be specified with a 422 (Unprocessable
|
||||
Entity) response ([RFC4918], Section 11.2) when the server
|
||||
understands the patch document and the syntax of the patch
|
||||
document appears to be valid, but the server is incapable of
|
||||
processing the request. This might include attempts to modify a
|
||||
resource in a way that would cause the resource to become invalid;
|
||||
for instance, a modification to a well-formed XML document that
|
||||
would cause it to no longer be well-formed. There may also be
|
||||
more specific errors like "Conflicting State" that could be
|
||||
signaled with this status code, but the more specific error would
|
||||
generally be more helpful.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 5]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
Resource not found: Can be specified with a 404 (Not Found) status
|
||||
code when the client attempted to apply a patch document to a non-
|
||||
existent resource, but the patch document chosen cannot be applied
|
||||
to a non-existent resource.
|
||||
|
||||
Conflicting state: Can be specified with a 409 (Conflict) status
|
||||
code when the request cannot be applied given the state of the
|
||||
resource. For example, if the client attempted to apply a
|
||||
structural modification and the structures assumed to exist did
|
||||
not exist (with XML, a patch might specify changing element 'foo'
|
||||
to element 'bar' but element 'foo' might not exist).
|
||||
|
||||
Conflicting modification: When a client uses either the If-Match or
|
||||
If-Unmodified-Since header to define a precondition, and that
|
||||
precondition failed, then the 412 (Precondition Failed) error is
|
||||
most helpful to the client. However, that response makes no sense
|
||||
if there was no precondition on the request. In cases when the
|
||||
server detects a possible conflicting modification and no
|
||||
precondition was defined in the request, the server can return a
|
||||
409 (Conflict) response.
|
||||
|
||||
Concurrent modification: Some applications of PATCH might require
|
||||
the server to process requests in the order in which they are
|
||||
received. If a server is operating under those restrictions, and
|
||||
it receives concurrent requests to modify the same resource, but
|
||||
is unable to queue those requests, the server can usefully
|
||||
indicate this error by using a 409 (Conflict) response.
|
||||
|
||||
Note that the 409 Conflict response gives reasonably consistent
|
||||
information to clients. Depending on the application and the nature
|
||||
of the patch format, the client might be able to reissue the request
|
||||
as is (e.g., an instruction to append a line to a log file), have to
|
||||
retrieve the resource content to recalculate a patch, or have to fail
|
||||
the operation.
|
||||
|
||||
Other HTTP status codes can also be used under the appropriate
|
||||
circumstances.
|
||||
|
||||
The entity body of error responses SHOULD contain enough information
|
||||
to communicate the nature of the error to the client. The content-
|
||||
type of the response entity can vary across implementations.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 6]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
3. Advertising Support in OPTIONS
|
||||
|
||||
A server can advertise its support for the PATCH method by adding it
|
||||
to the listing of allowed methods in the "Allow" OPTIONS response
|
||||
header defined in HTTP/1.1. The PATCH method MAY appear in the
|
||||
"Allow" header even if the Accept-Patch header is absent, in which
|
||||
case the list of allowed patch documents is not advertised.
|
||||
|
||||
3.1. The Accept-Patch Header
|
||||
|
||||
This specification introduces a new response header Accept-Patch used
|
||||
to specify the patch document formats accepted by the server.
|
||||
Accept-Patch SHOULD appear in the OPTIONS response for any resource
|
||||
that supports the use of the PATCH method. The presence of the
|
||||
Accept-Patch header in response to any method is an implicit
|
||||
indication that PATCH is allowed on the resource identified by the
|
||||
Request-URI. The presence of a specific patch document format in
|
||||
this header indicates that that specific format is allowed on the
|
||||
resource identified by the Request-URI.
|
||||
|
||||
Accept-Patch = "Accept-Patch" ":" 1#media-type
|
||||
|
||||
The Accept-Patch header specifies a comma-separated listing of media-
|
||||
types (with optional parameters) as defined by [RFC2616], Section
|
||||
3.7.
|
||||
|
||||
Example:
|
||||
|
||||
Accept-Patch: text/example;charset=utf-8
|
||||
|
||||
3.2. Example OPTIONS Request and Response
|
||||
|
||||
[request]
|
||||
|
||||
OPTIONS /example/buddies.xml HTTP/1.1
|
||||
Host: www.example.com
|
||||
|
||||
[response]
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Allow: GET, PUT, POST, OPTIONS, HEAD, DELETE, PATCH
|
||||
Accept-Patch: application/example, text/example
|
||||
|
||||
The examples show a server that supports PATCH generally using two
|
||||
hypothetical patch document formats.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 7]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
4. IANA Considerations
|
||||
|
||||
4.1. The Accept-Patch Response Header
|
||||
|
||||
The Accept-Patch response header has been added to the permanent
|
||||
registry (see [RFC3864]).
|
||||
|
||||
Header field name: Accept-Patch
|
||||
|
||||
Applicable Protocol: HTTP
|
||||
|
||||
Author/Change controller: IETF
|
||||
|
||||
Specification document: this specification
|
||||
|
||||
5. Security Considerations
|
||||
|
||||
The security considerations for PATCH are nearly identical to the
|
||||
security considerations for PUT ([RFC2616], Section 9.6). These
|
||||
include authorizing requests (possibly through access control and/or
|
||||
authentication) and ensuring that data is not corrupted through
|
||||
transport errors or through accidental overwrites. Whatever
|
||||
mechanisms are used for PUT can be used for PATCH as well. The
|
||||
following considerations apply especially to PATCH.
|
||||
|
||||
A document that is patched might be more likely to be corrupted than
|
||||
a document that is overridden in entirety, but that concern can be
|
||||
addressed through the use of mechanisms such as conditional requests
|
||||
using ETags and the If-Match request header as described in
|
||||
Section 2. If a PATCH request fails, the client can issue a GET
|
||||
request to the resource to see what state it is in. In some cases,
|
||||
the client might be able to check the contents of the resource to see
|
||||
if the PATCH request can be resent, but in other cases, the attempt
|
||||
will just fail and/or a user will have to verify intent. In the case
|
||||
of a failure of the underlying transport channel, where a PATCH
|
||||
response is not received before the channel fails or some other
|
||||
timeout happens, the client might have to issue a GET request to see
|
||||
whether the request was applied. The client might want to ensure
|
||||
that the GET request bypasses caches using mechanisms described in
|
||||
HTTP specifications (see, for example, Section 13.1.6 of [RFC2616]).
|
||||
|
||||
Sometimes an HTTP intermediary might try to detect viruses being sent
|
||||
via HTTP by checking the body of the PUT/POST request or GET
|
||||
response. The PATCH method complicates such watch-keeping because
|
||||
neither the source document nor the patch document might be a virus,
|
||||
yet the result could be. This security consideration is not
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 8]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
materially different from those already introduced by byte-range
|
||||
downloads, downloading patch documents, uploading zipped (compressed)
|
||||
files, and so on.
|
||||
|
||||
Individual patch documents will have their own specific security
|
||||
considerations that will likely vary depending on the types of
|
||||
resources being patched. The considerations for patched binary
|
||||
resources, for instance, will be different than those for patched XML
|
||||
documents. Servers MUST take adequate precautions to ensure that
|
||||
malicious clients cannot consume excessive server resources (e.g.,
|
||||
CPU, disk I/O) through the client's use of PATCH.
|
||||
|
||||
6. References
|
||||
|
||||
6.1. Normative References
|
||||
|
||||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
|
||||
Requirement Levels", BCP 14, RFC 2119, March 1997.
|
||||
|
||||
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
|
||||
Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
|
||||
Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
|
||||
|
||||
[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration
|
||||
Procedures for Message Header Fields", BCP 90, RFC 3864,
|
||||
September 2004.
|
||||
|
||||
6.2. Informative References
|
||||
|
||||
[RFC4918] Dusseault, L., "HTTP Extensions for Web Distributed
|
||||
Authoring and Versioning (WebDAV)", RFC 4918, June 2007.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 9]
|
||||
|
||||
RFC 5789 HTTP PATCH March 2010
|
||||
|
||||
|
||||
Appendix A. Acknowledgements
|
||||
|
||||
PATCH is not a new concept, it first appeared in HTTP in drafts of
|
||||
version 1.1 written by Roy Fielding and Henrik Frystyk and also
|
||||
appears in Section 19.6.1.1 of RFC 2068.
|
||||
|
||||
Thanks to Adam Roach, Chris Sharp, Julian Reschke, Geoff Clemm, Scott
|
||||
Lawrence, Jeffrey Mogul, Roy Fielding, Greg Stein, Jim Luther, Alex
|
||||
Rousskov, Jamie Lokier, Joe Hildebrand, Mark Nottingham, Michael
|
||||
Balloni, Cyrus Daboo, Brian Carpenter, John Klensin, Eliot Lear, SM,
|
||||
and Bernie Hoeneisen for review and advice on this document. In
|
||||
particular, Julian Reschke did repeated reviews, made many useful
|
||||
suggestions, and was critical to the publication of this document.
|
||||
|
||||
Authors' Addresses
|
||||
|
||||
Lisa Dusseault
|
||||
Linden Lab
|
||||
945 Battery Street
|
||||
San Francisco, CA 94111
|
||||
USA
|
||||
|
||||
EMail: lisa.dusseault@gmail.com
|
||||
|
||||
|
||||
James M. Snell
|
||||
|
||||
EMail: jasnell@gmail.com
|
||||
URI: http://www.snellspace.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dusseault & Snell Standards Track [Page 10]
|
||||
|
1235
vendor/sabre/dav/docs/rfc6047.txt
vendored
Normal file
1235
vendor/sabre/dav/docs/rfc6047.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3027
vendor/sabre/dav/docs/rfc6321.txt
vendored
Normal file
3027
vendor/sabre/dav/docs/rfc6321.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4147
vendor/sabre/dav/docs/rfc6350.txt
vendored
Normal file
4147
vendor/sabre/dav/docs/rfc6350.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1235
vendor/sabre/dav/docs/rfc6351.txt
vendored
Normal file
1235
vendor/sabre/dav/docs/rfc6351.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2691
vendor/sabre/dav/docs/rfc6352.txt
vendored
Normal file
2691
vendor/sabre/dav/docs/rfc6352.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
56
vendor/sabre/dav/examples/addressbookserver.php
vendored
Normal file
56
vendor/sabre/dav/examples/addressbookserver.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
Addressbook/CardDAV server example
|
||||
|
||||
This server features CardDAV support
|
||||
|
||||
*/
|
||||
|
||||
// settings
|
||||
date_default_timezone_set('Canada/Eastern');
|
||||
|
||||
// Make sure this setting is turned on and reflect the root url for your WebDAV server.
|
||||
// This can be for example the root / or a complete path to your server script
|
||||
$baseUri = '/';
|
||||
|
||||
/* Database */
|
||||
$pdo = new PDO('sqlite:data/db.sqlite');
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
//Mapping PHP errors to exceptions
|
||||
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
|
||||
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
}
|
||||
set_error_handler("exception_error_handler");
|
||||
|
||||
// Autoloader
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
// Backends
|
||||
$authBackend = new Sabre\DAV\Auth\Backend\PDO($pdo);
|
||||
$principalBackend = new Sabre\DAVACL\PrincipalBackend\PDO($pdo);
|
||||
$carddavBackend = new Sabre\CardDAV\Backend\PDO($pdo);
|
||||
//$caldavBackend = new Sabre\CalDAV\Backend\PDO($pdo);
|
||||
|
||||
// Setting up the directory tree //
|
||||
$nodes = array(
|
||||
new Sabre\DAVACL\PrincipalCollection($principalBackend),
|
||||
// new Sabre\CalDAV\CalendarRootNode($authBackend, $caldavBackend),
|
||||
new Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend),
|
||||
);
|
||||
|
||||
// The object tree needs in turn to be passed to the server class
|
||||
$server = new Sabre\DAV\Server($nodes);
|
||||
$server->setBaseUri($baseUri);
|
||||
|
||||
// Plugins
|
||||
$server->addPlugin(new Sabre\DAV\Auth\Plugin($authBackend,'SabreDAV'));
|
||||
$server->addPlugin(new Sabre\DAV\Browser\Plugin());
|
||||
//$server->addPlugin(new Sabre\CalDAV\Plugin());
|
||||
$server->addPlugin(new Sabre\CardDAV\Plugin());
|
||||
$server->addPlugin(new Sabre\DAVACL\Plugin());
|
||||
|
||||
// And off we go!
|
||||
$server->exec();
|
26
vendor/sabre/dav/examples/basicauth.php
vendored
Normal file
26
vendor/sabre/dav/examples/basicauth.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
// !!!! Make sure the Sabre directory is in the include_path !!!
|
||||
// example:
|
||||
// set_include_path('lib/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
// settings
|
||||
date_default_timezone_set('Canada/Eastern');
|
||||
|
||||
// Files we need
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
$u = 'admin';
|
||||
$p = '1234';
|
||||
|
||||
$auth = new \Sabre\HTTP\BasicAuth();
|
||||
|
||||
$result = $auth->getUserPass();
|
||||
|
||||
if (!$result || $result[0]!=$u || $result[1]!=$p) {
|
||||
|
||||
$auth->requireLogin();
|
||||
echo "Authentication required\n";
|
||||
die();
|
||||
|
||||
}
|
25
vendor/sabre/dav/examples/digestauth.php
vendored
Normal file
25
vendor/sabre/dav/examples/digestauth.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
// !!!! Make sure the Sabre directory is in the include_path !!!
|
||||
// example:
|
||||
// set_include_path('lib/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
// settings
|
||||
date_default_timezone_set('Canada/Eastern');
|
||||
|
||||
// Files we need
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
$u = 'admin';
|
||||
$p = '1234';
|
||||
|
||||
$auth = new \Sabre\HTTP\DigestAuth();
|
||||
$auth->init();
|
||||
|
||||
if ($auth->getUsername() != $u || !$auth->validatePassword($p)) {
|
||||
|
||||
$auth->requireLogin();
|
||||
echo "Authentication required\n";
|
||||
die();
|
||||
|
||||
}
|
123
vendor/sabre/dav/examples/simplefsserver.php
vendored
Normal file
123
vendor/sabre/dav/examples/simplefsserver.php
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
// !!!! Make sure the Sabre directory is in the include_path !!!
|
||||
// example:
|
||||
// set_include_path('lib/' . PATH_SEPARATOR . get_include_path());
|
||||
|
||||
/*
|
||||
|
||||
This example demonstrates a simple way to create your own virtual filesystems.
|
||||
By extending the _File and Directory classes, you can easily create a tree
|
||||
based on various datasources.
|
||||
|
||||
The most obvious example is the filesystem itself. A more complete and documented
|
||||
example can be found in:
|
||||
|
||||
lib/Sabre/DAV/FS/Node.php
|
||||
lib/Sabre/DAV/FS/Directory.php
|
||||
lib/Sabre/DAV/FS/File.php
|
||||
|
||||
*/
|
||||
|
||||
// settings
|
||||
date_default_timezone_set('Canada/Eastern');
|
||||
$publicDir = 'public';
|
||||
|
||||
// Files we need
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
class MyCollection extends Sabre\DAV\Collection {
|
||||
|
||||
private $myPath;
|
||||
|
||||
function __construct($myPath) {
|
||||
|
||||
$this->myPath = $myPath;
|
||||
|
||||
}
|
||||
|
||||
function getChildren() {
|
||||
|
||||
$children = array();
|
||||
// Loop through the directory, and create objects for each node
|
||||
foreach(scandir($this->myPath) as $node) {
|
||||
|
||||
// Ignoring files staring with .
|
||||
if ($node[0]==='.') continue;
|
||||
|
||||
$children[] = $this->getChild($node);
|
||||
|
||||
}
|
||||
|
||||
return $children;
|
||||
|
||||
}
|
||||
|
||||
function getChild($name) {
|
||||
|
||||
$path = $this->myPath . '/' . $name;
|
||||
|
||||
// We have to throw a NotFound exception if the file didn't exist
|
||||
if (!file\exists($this->myPath)) throw new \Sabre\DAV\Exception\NotFound('The file with name: ' . $name . ' could not be found');
|
||||
// Some added security
|
||||
|
||||
if ($name[0]=='.') throw new \Sabre\DAV\Exception\Forbidden('Access denied');
|
||||
|
||||
if (is_dir($path)) {
|
||||
|
||||
return new \MyCollection($name);
|
||||
|
||||
} else {
|
||||
|
||||
return new \MyFile($path);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getName() {
|
||||
|
||||
return basename($this->myPath);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MyFile extends \Sabre\DAV\File {
|
||||
|
||||
private $myPath;
|
||||
|
||||
function __construct($myPath) {
|
||||
|
||||
$this->myPath = $myPath;
|
||||
|
||||
}
|
||||
|
||||
function getName() {
|
||||
|
||||
return basename($this->myPath);
|
||||
|
||||
}
|
||||
|
||||
function get() {
|
||||
|
||||
return fopen($this->myPath,'r');
|
||||
|
||||
}
|
||||
|
||||
function getSize() {
|
||||
|
||||
return filesize($this->myPath);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Make sure there is a directory in your current directory named 'public'. We will be exposing that directory to WebDAV
|
||||
$rootNode = new \MyCollection($publicDir);
|
||||
|
||||
// The rootNode needs to be passed to the server object.
|
||||
$server = new \Sabre\DAV\Server($rootNode);
|
||||
|
||||
// And off we go!
|
||||
$server->exec();
|
18
vendor/sabre/dav/examples/sql/mysql.addressbook.sql
vendored
Normal file
18
vendor/sabre/dav/examples/sql/mysql.addressbook.sql
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
CREATE TABLE addressbooks (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARCHAR(255),
|
||||
displayname VARCHAR(255),
|
||||
uri VARCHAR(200),
|
||||
description TEXT,
|
||||
ctag INT(11) UNSIGNED NOT NULL DEFAULT '1',
|
||||
UNIQUE(principaluri, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE cards (
|
||||
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
addressbookid INT(11) UNSIGNED NOT NULL,
|
||||
carddata MEDIUMBLOB,
|
||||
uri VARCHAR(200),
|
||||
lastmodified INT(11) UNSIGNED
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
28
vendor/sabre/dav/examples/sql/mysql.calendars.sql
vendored
Normal file
28
vendor/sabre/dav/examples/sql/mysql.calendars.sql
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
CREATE TABLE calendarobjects (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
calendardata MEDIUMBLOB,
|
||||
uri VARCHAR(200),
|
||||
calendarid INTEGER UNSIGNED NOT NULL,
|
||||
lastmodified INT(11) UNSIGNED,
|
||||
etag VARCHAR(32),
|
||||
size INT(11) UNSIGNED NOT NULL,
|
||||
componenttype VARCHAR(8),
|
||||
firstoccurence INT(11) UNSIGNED,
|
||||
lastoccurence INT(11) UNSIGNED,
|
||||
UNIQUE(calendarid, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principaluri VARCHAR(100),
|
||||
displayname VARCHAR(100),
|
||||
uri VARCHAR(200),
|
||||
ctag INTEGER UNSIGNED NOT NULL DEFAULT '0',
|
||||
description TEXT,
|
||||
calendarorder INTEGER UNSIGNED NOT NULL DEFAULT '0',
|
||||
calendarcolor VARCHAR(10),
|
||||
timezone TEXT,
|
||||
components VARCHAR(20),
|
||||
transparent TINYINT(1) NOT NULL DEFAULT '0',
|
||||
UNIQUE(principaluri, uri)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
13
vendor/sabre/dav/examples/sql/mysql.locks.sql
vendored
Normal file
13
vendor/sabre/dav/examples/sql/mysql.locks.sql
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
CREATE TABLE locks (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
owner VARCHAR(100),
|
||||
timeout INTEGER UNSIGNED,
|
||||
created INTEGER,
|
||||
token VARCHAR(100),
|
||||
scope TINYINT,
|
||||
depth TINYINT,
|
||||
uri VARCHAR(1000),
|
||||
INDEX(token),
|
||||
INDEX(uri)
|
||||
);
|
||||
|
22
vendor/sabre/dav/examples/sql/mysql.principals.sql
vendored
Normal file
22
vendor/sabre/dav/examples/sql/mysql.principals.sql
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
CREATE TABLE principals (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
uri VARCHAR(200) NOT NULL,
|
||||
email VARCHAR(80),
|
||||
displayname VARCHAR(80),
|
||||
vcardurl VARCHAR(255),
|
||||
UNIQUE(uri)
|
||||
);
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
principal_id INTEGER UNSIGNED NOT NULL,
|
||||
member_id INTEGER UNSIGNED NOT NULL,
|
||||
UNIQUE(principal_id, member_id)
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO principals (uri,email,displayname) VALUES
|
||||
('principals/admin', 'admin@example.org','Administrator'),
|
||||
('principals/admin/calendar-proxy-read', null, null),
|
||||
('principals/admin/calendar-proxy-write', null, null);
|
||||
|
9
vendor/sabre/dav/examples/sql/mysql.users.sql
vendored
Normal file
9
vendor/sabre/dav/examples/sql/mysql.users.sql
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE TABLE users (
|
||||
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
username VARCHAR(50),
|
||||
digesta1 VARCHAR(32),
|
||||
UNIQUE(username)
|
||||
);
|
||||
|
||||
INSERT INTO users (username,digesta1) VALUES
|
||||
('admin', '87fd274b7b6c01e48d7c2f965da8ddf7');
|
33
vendor/sabre/dav/examples/sql/pgsql.addressbook.sql
vendored
Normal file
33
vendor/sabre/dav/examples/sql/pgsql.addressbook.sql
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
CREATE TABLE addressbooks (
|
||||
id SERIAL NOT NULL,
|
||||
principaluri VARCHAR(255),
|
||||
displayname VARCHAR(255),
|
||||
uri VARCHAR(200),
|
||||
description TEXT,
|
||||
ctag INTEGER NOT NULL DEFAULT 1
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY addressbooks
|
||||
ADD CONSTRAINT addressbooks_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX addressbooks_ukey
|
||||
ON addressbooks USING btree (principaluri, uri);
|
||||
|
||||
CREATE TABLE cards (
|
||||
id SERIAL NOT NULL,
|
||||
addressbookid INTEGER NOT NULL,
|
||||
carddata TEXT,
|
||||
uri VARCHAR(200),
|
||||
lastmodified INTEGER
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY cards
|
||||
ADD CONSTRAINT cards_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX cards_ukey
|
||||
ON cards USING btree (addressbookid, uri);
|
||||
|
||||
ALTER TABLE ONLY cards
|
||||
ADD CONSTRAINT cards_addressbookid_fkey FOREIGN KEY (addressbookid) REFERENCES addressbooks(id)
|
||||
ON DELETE CASCADE;
|
||||
|
42
vendor/sabre/dav/examples/sql/pgsql.calendars.sql
vendored
Normal file
42
vendor/sabre/dav/examples/sql/pgsql.calendars.sql
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
CREATE TABLE calendars (
|
||||
id SERIAL NOT NULL,
|
||||
principaluri VARCHAR(100),
|
||||
displayname VARCHAR(100),
|
||||
uri VARCHAR(200),
|
||||
ctag INTEGER NOT NULL DEFAULT 0,
|
||||
description TEXT,
|
||||
calendarorder INTEGER NOT NULL DEFAULT 0,
|
||||
calendarcolor VARCHAR(10),
|
||||
timezone TEXT,
|
||||
components VARCHAR(20),
|
||||
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,
|
||||
calendarid INTEGER NOT NULL,
|
||||
calendardata TEXT,
|
||||
uri VARCHAR(200),
|
||||
etag VARCHAR(32),
|
||||
size INTEGER NOT NULL,
|
||||
componenttype VARCHAR(8),
|
||||
lastmodified INTEGER,
|
||||
firstoccurence INTEGER,
|
||||
lastoccurence INTEGER
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY calendarobjects
|
||||
ADD CONSTRAINT calendarobjects_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX calendarobjects_ukey
|
||||
ON calendarobjects USING btree (calendarid, uri);
|
||||
|
||||
ALTER TABLE ONLY calendarobjects
|
||||
ADD CONSTRAINT calendarobjects_calendarid_fkey FOREIGN KEY (calendarid) REFERENCES calendars(id)
|
||||
ON DELETE CASCADE;
|
13
vendor/sabre/dav/examples/sql/pgsql.locks.sql
vendored
Normal file
13
vendor/sabre/dav/examples/sql/pgsql.locks.sql
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
CREATE TABLE locks (
|
||||
id SERIAL NOT NULL,
|
||||
owner VARCHAR(100),
|
||||
timeout INTEGER,
|
||||
created INTEGER,
|
||||
token VARCHAR(100),
|
||||
scope smallint,
|
||||
depth smallint,
|
||||
uri text
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY locks
|
||||
ADD CONSTRAINT locks_pkey PRIMARY KEY (id);
|
40
vendor/sabre/dav/examples/sql/pgsql.principals.sql
vendored
Normal file
40
vendor/sabre/dav/examples/sql/pgsql.principals.sql
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
CREATE TABLE principals (
|
||||
id SERIAL NOT NULL,
|
||||
uri VARCHAR(100) NOT NULL,
|
||||
email VARCHAR(80),
|
||||
displayname VARCHAR(80),
|
||||
vcardurl VARCHAR(255)
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY principals
|
||||
ADD CONSTRAINT principals_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX principals_ukey
|
||||
ON principals USING btree (uri);
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id SERIAL NOT NULL,
|
||||
principal_id INTEGER NOT NULL,
|
||||
member_id INTEGER NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY groupmembers
|
||||
ADD CONSTRAINT groupmembers_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX groupmembers_ukey
|
||||
ON groupmembers USING btree (principal_id, member_id);
|
||||
|
||||
ALTER TABLE ONLY groupmembers
|
||||
ADD CONSTRAINT groupmembers_principal_id_fkey FOREIGN KEY (principal_id) REFERENCES principals(id)
|
||||
ON DELETE CASCADE;
|
||||
|
||||
-- Is this correct correct link ... or not?
|
||||
-- ALTER TABLE ONLY groupmembers
|
||||
-- ADD CONSTRAINT groupmembers_member_id_id_fkey FOREIGN KEY (member_id) REFERENCES users(id)
|
||||
-- ON DELETE CASCADE;
|
||||
|
||||
INSERT INTO principals (uri,email,displayname) VALUES
|
||||
('principals/admin', 'admin@example.org','Administrator'),
|
||||
('principals/admin/calendar-proxy-read', null, null),
|
||||
('principals/admin/calendar-proxy-write', null, null);
|
||||
|
15
vendor/sabre/dav/examples/sql/pgsql.users.sql
vendored
Normal file
15
vendor/sabre/dav/examples/sql/pgsql.users.sql
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
CREATE TABLE users (
|
||||
id SERIAL NOT NULL,
|
||||
username VARCHAR(50),
|
||||
digesta1 VARCHAR(32),
|
||||
UNIQUE(username)
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY users
|
||||
ADD CONSTRAINT users_pkey PRIMARY KEY (id);
|
||||
|
||||
CREATE UNIQUE INDEX users_ukey
|
||||
ON users USING btree (username);
|
||||
|
||||
INSERT INTO users (username,digesta1) VALUES
|
||||
('admin', '87fd274b7b6c01e48d7c2f965da8ddf7');
|
17
vendor/sabre/dav/examples/sql/sqlite.addressbooks.sql
vendored
Normal file
17
vendor/sabre/dav/examples/sql/sqlite.addressbooks.sql
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
CREATE TABLE addressbooks (
|
||||
id integer primary key asc,
|
||||
principaluri text,
|
||||
displayname text,
|
||||
uri text,
|
||||
description text,
|
||||
ctag integer
|
||||
);
|
||||
|
||||
CREATE TABLE cards (
|
||||
id integer primary key asc,
|
||||
addressbookid integer,
|
||||
carddata blob,
|
||||
uri text,
|
||||
lastmodified integer
|
||||
);
|
||||
|
26
vendor/sabre/dav/examples/sql/sqlite.calendars.sql
vendored
Normal file
26
vendor/sabre/dav/examples/sql/sqlite.calendars.sql
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
CREATE TABLE calendarobjects (
|
||||
id integer primary key asc,
|
||||
calendardata blob,
|
||||
uri text,
|
||||
calendarid integer,
|
||||
lastmodified integer,
|
||||
etag text,
|
||||
size integer,
|
||||
componenttype text,
|
||||
firstoccurence integer,
|
||||
lastoccurence integer
|
||||
);
|
||||
|
||||
CREATE TABLE calendars (
|
||||
id integer primary key asc,
|
||||
principaluri text,
|
||||
displayname text,
|
||||
uri text,
|
||||
ctag integer,
|
||||
description text,
|
||||
calendarorder integer,
|
||||
calendarcolor text,
|
||||
timezone text,
|
||||
components text,
|
||||
transparent bool
|
||||
);
|
12
vendor/sabre/dav/examples/sql/sqlite.locks.sql
vendored
Normal file
12
vendor/sabre/dav/examples/sql/sqlite.locks.sql
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
BEGIN TRANSACTION;
|
||||
CREATE TABLE locks (
|
||||
id integer primary key asc,
|
||||
owner text,
|
||||
timeout integer,
|
||||
created integer,
|
||||
token text,
|
||||
scope integer,
|
||||
depth integer,
|
||||
uri text
|
||||
);
|
||||
COMMIT;
|
21
vendor/sabre/dav/examples/sql/sqlite.principals.sql
vendored
Normal file
21
vendor/sabre/dav/examples/sql/sqlite.principals.sql
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
CREATE TABLE principals (
|
||||
id INTEGER PRIMARY KEY ASC,
|
||||
uri TEXT,
|
||||
email TEXT,
|
||||
displayname TEXT,
|
||||
vcardurl TEXT,
|
||||
UNIQUE(uri)
|
||||
);
|
||||
|
||||
CREATE TABLE groupmembers (
|
||||
id INTEGER PRIMARY KEY ASC,
|
||||
principal_id INTEGER,
|
||||
member_id INTEGER,
|
||||
UNIQUE(principal_id, member_id)
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin', 'admin@example.org','Administrator');
|
||||
INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-read', null, null);
|
||||
INSERT INTO principals (uri,email,displayname) VALUES ('principals/admin/calendar-proxy-write', null, null);
|
||||
|
9
vendor/sabre/dav/examples/sql/sqlite.users.sql
vendored
Normal file
9
vendor/sabre/dav/examples/sql/sqlite.users.sql
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE TABLE users (
|
||||
id integer primary key asc,
|
||||
username TEXT,
|
||||
digesta1 TEXT,
|
||||
UNIQUE(username)
|
||||
);
|
||||
|
||||
INSERT INTO users (username,digesta1) VALUES
|
||||
('admin', '87fd274b7b6c01e48d7c2f965da8ddf7');
|
16
vendor/sabre/dav/examples/webserver/apache2_htaccess.conf
vendored
Normal file
16
vendor/sabre/dav/examples/webserver/apache2_htaccess.conf
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
RewriteEngine On
|
||||
# This makes every request go to server.php
|
||||
RewriteRule (.*) server.php [L]
|
||||
|
||||
# Output buffering needs to be off, to prevent high memory usage
|
||||
php_flag output_buffering off
|
||||
|
||||
# This is also to prevent high memory usage
|
||||
php_flag always_populate_raw_post_data off
|
||||
|
||||
# This is almost a given, but magic quotes is *still* on on some
|
||||
# linux distributions
|
||||
php_flag magic_quotes_gpc off
|
||||
|
||||
# SabreDAV is not compatible with mbstring function overloading
|
||||
php_flag mbstring.func_overload off
|
33
vendor/sabre/dav/examples/webserver/apache2_vhost.conf
vendored
Normal file
33
vendor/sabre/dav/examples/webserver/apache2_vhost.conf
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# This is a sample configuration to setup a dedicated Apache vhost for WebDAV.
|
||||
#
|
||||
# The main thing that should be configured is the servername, and the path to
|
||||
# your SabreDAV installation (DocumentRoot).
|
||||
#
|
||||
# This configuration assumed mod_php5 is used, as it sets a few default php
|
||||
# settings as well.
|
||||
<VirtualHost *:*>
|
||||
|
||||
# Don't forget to change the server name
|
||||
# ServerName dav.example.org
|
||||
|
||||
# The DocumentRoot is also required
|
||||
# DocumentRoot /home/sabredav/
|
||||
|
||||
RewriteEngine On
|
||||
# This makes every request go to server.php
|
||||
RewriteRule ^/(.*)$ /server.php [L]
|
||||
|
||||
# Output buffering needs to be off, to prevent high memory usage
|
||||
php_flag output_buffering off
|
||||
|
||||
# This is also to prevent high memory usage
|
||||
php_flag always_populate_raw_post_data off
|
||||
|
||||
# This is almost a given, but magic quotes is *still* on on some
|
||||
# linux distributions
|
||||
php_flag magic_quotes_gpc off
|
||||
|
||||
# SabreDAV is not compatible with mbstring function overloading
|
||||
php_flag mbstring.func_overload off
|
||||
|
||||
</VirtualHost *:*>
|
21
vendor/sabre/dav/examples/webserver/apache2_vhost_cgi.conf
vendored
Normal file
21
vendor/sabre/dav/examples/webserver/apache2_vhost_cgi.conf
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# This is a sample configuration to setup a dedicated Apache vhost for WebDAV.
|
||||
#
|
||||
# The main thing that should be configured is the servername, and the path to
|
||||
# your SabreDAV installation (DocumentRoot).
|
||||
#
|
||||
# This configuration assumes CGI or FastCGI is used.
|
||||
<VirtualHost *:*>
|
||||
|
||||
# Don't forget to change the server name
|
||||
# ServerName dav.example.org
|
||||
|
||||
# The DocumentRoot is also required
|
||||
# DocumentRoot /home/sabredav/
|
||||
|
||||
# This makes every request go to server.php. This also makes sure
|
||||
# the Authentication information is available. If your server script is
|
||||
# not called server.php, be sure to change it.
|
||||
RewriteEngine On
|
||||
RewriteRule ^/(.*)$ /server.php [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
</VirtualHost *:*>
|
155
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/AbstractBackend.php
vendored
Normal file
155
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/AbstractBackend.php
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Backend;
|
||||
|
||||
use Sabre\VObject;
|
||||
use Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* Abstract Calendaring backend. Extend this class to create your own backends.
|
||||
*
|
||||
* Checkout the BackendInterface for all the methods that must be implemented.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
abstract class AbstractBackend implements BackendInterface {
|
||||
|
||||
/**
|
||||
* Updates properties for a calendar.
|
||||
*
|
||||
* The mutations array uses the propertyName in clark-notation as key,
|
||||
* and the array value for the property value. In the case a property
|
||||
* should be deleted, the property value will be null.
|
||||
*
|
||||
* This method must be atomic. If one property cannot be changed, the
|
||||
* entire operation must fail.
|
||||
*
|
||||
* If the operation was successful, true can be returned.
|
||||
* If the operation failed, false can be returned.
|
||||
*
|
||||
* Deletion of a non-existent property is always successful.
|
||||
*
|
||||
* Lastly, it is optional to return detailed information about any
|
||||
* failures. In this case an array should be returned with the following
|
||||
* structure:
|
||||
*
|
||||
* array(
|
||||
* 403 => array(
|
||||
* '{DAV:}displayname' => null,
|
||||
* ),
|
||||
* 424 => array(
|
||||
* '{DAV:}owner' => null,
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* In this example it was forbidden to update {DAV:}displayname.
|
||||
* (403 Forbidden), which in turn also caused {DAV:}owner to fail
|
||||
* (424 Failed Dependency) because the request needs to be atomic.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param array $mutations
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateCalendar($calendarId, array $mutations) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
* The calendar-query is defined in RFC4791 : CalDAV. Using the
|
||||
* calendar-query it is possible for a client to request a specific set of
|
||||
* object, based on contents of iCalendar properties, date-ranges and
|
||||
* iCalendar component types (VTODO, VEVENT).
|
||||
*
|
||||
* This method should just return a list of (relative) urls that match this
|
||||
* query.
|
||||
*
|
||||
* The list of filters are specified as an array. The exact array is
|
||||
* documented by \Sabre\CalDAV\CalendarQueryParser.
|
||||
*
|
||||
* Note that it is extremely likely that getCalendarObject for every path
|
||||
* returned from this method will be called almost immediately after. You
|
||||
* may want to anticipate this to speed up these requests.
|
||||
*
|
||||
* This method provides a default implementation, which parses *all* the
|
||||
* iCalendar objects in the specified calendar.
|
||||
*
|
||||
* This default may well be good enough for personal use, and calendars
|
||||
* that aren't very large. But if you anticipate high usage, big calendars
|
||||
* or high loads, you are strongly adviced to optimize certain paths.
|
||||
*
|
||||
* The best way to do so is override this method and to optimize
|
||||
* specifically for 'common filters'.
|
||||
*
|
||||
* Requests that are extremely common are:
|
||||
* * requests for just VEVENTS
|
||||
* * requests for just VTODO
|
||||
* * requests with a time-range-filter on either VEVENT or VTODO.
|
||||
*
|
||||
* ..and combinations of these requests. It may not be worth it to try to
|
||||
* handle every possible situation and just rely on the (relatively
|
||||
* easy to use) CalendarQueryValidator to handle the rest.
|
||||
*
|
||||
* Note that especially time-range-filters may be difficult to parse. A
|
||||
* time-range filter specified on a VEVENT must for instance also handle
|
||||
* recurrence rules correctly.
|
||||
* A good example of how to interprete all these filters can also simply
|
||||
* be found in \Sabre\CalDAV\CalendarQueryFilter. This class is as correct
|
||||
* as possible, so it gives you a good idea on what type of stuff you need
|
||||
* to think of.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param array $filters
|
||||
* @return array
|
||||
*/
|
||||
public function calendarQuery($calendarId, array $filters) {
|
||||
|
||||
$result = array();
|
||||
$objects = $this->getCalendarObjects($calendarId);
|
||||
|
||||
$validator = new \Sabre\CalDAV\CalendarQueryValidator();
|
||||
|
||||
foreach($objects as $object) {
|
||||
|
||||
if ($this->validateFilterForObject($object, $filters)) {
|
||||
$result[] = $object['uri'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method validates if a filters (as passed to calendarQuery) matches
|
||||
* the given object.
|
||||
*
|
||||
* @param array $object
|
||||
* @param array $filters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateFilterForObject(array $object, array $filters) {
|
||||
|
||||
// Unfortunately, setting the 'calendardata' here is optional. If
|
||||
// it was excluded, we actually need another call to get this as
|
||||
// well.
|
||||
if (!isset($object['calendardata'])) {
|
||||
$object = $this->getCalendarObject($object['calendarid'], $object['uri']);
|
||||
}
|
||||
|
||||
$data = is_resource($object['calendardata'])?stream_get_contents($object['calendardata']):$object['calendardata'];
|
||||
$vObject = VObject\Reader::read($data);
|
||||
|
||||
$validator = new CalDAV\CalendarQueryValidator();
|
||||
return $validator->validate($vObject, $filters);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
233
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/BackendInterface.php
vendored
Normal file
233
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/BackendInterface.php
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Backend;
|
||||
|
||||
/**
|
||||
* Every CalDAV backend must at least implement this interface.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface BackendInterface {
|
||||
|
||||
/**
|
||||
* 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, which the basename of the uri with which the calendar is
|
||||
* accessed.
|
||||
* * 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'.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @return array
|
||||
*/
|
||||
public function getCalendarsForUser($principalUri);
|
||||
|
||||
/**
|
||||
* 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 void
|
||||
*/
|
||||
public function createCalendar($principalUri,$calendarUri,array $properties);
|
||||
|
||||
/**
|
||||
* Updates properties for a calendar.
|
||||
*
|
||||
* The mutations array uses the propertyName in clark-notation as key,
|
||||
* and the array value for the property value. In the case a property
|
||||
* should be deleted, the property value will be null.
|
||||
*
|
||||
* This method must be atomic. If one property cannot be changed, the
|
||||
* entire operation must fail.
|
||||
*
|
||||
* If the operation was successful, true can be returned.
|
||||
* If the operation failed, false can be returned.
|
||||
*
|
||||
* Deletion of a non-existent property is always successful.
|
||||
*
|
||||
* Lastly, it is optional to return detailed information about any
|
||||
* failures. In this case an array should be returned with the following
|
||||
* structure:
|
||||
*
|
||||
* array(
|
||||
* 403 => array(
|
||||
* '{DAV:}displayname' => null,
|
||||
* ),
|
||||
* 424 => array(
|
||||
* '{DAV:}owner' => null,
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* In this example it was forbidden to update {DAV:}displayname.
|
||||
* (403 Forbidden), which in turn also caused {DAV:}owner to fail
|
||||
* (424 Failed Dependency) because the request needs to be atomic.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param array $mutations
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateCalendar($calendarId, array $mutations);
|
||||
|
||||
/**
|
||||
* Delete a calendar and all it's objects
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCalendar($calendarId);
|
||||
|
||||
/**
|
||||
* Returns all calendar objects within a calendar.
|
||||
*
|
||||
* Every item contains an array with the following keys:
|
||||
* * id - unique identifier which will be used for subsequent updates
|
||||
* * calendardata - The iCalendar-compatible calendar data
|
||||
* * uri - a unique key which will be used to construct the uri. This can be any arbitrary string.
|
||||
* * lastmodified - a timestamp of the last modification time
|
||||
* * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
|
||||
* ' "abcdef"')
|
||||
* * calendarid - The calendarid as it was passed to this function.
|
||||
* * size - The size of the calendar objects, in bytes.
|
||||
*
|
||||
* 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 mixed $calendarId
|
||||
* @return array
|
||||
*/
|
||||
public function getCalendarObjects($calendarId);
|
||||
|
||||
/**
|
||||
* Returns information from a single calendar object, based on it's object
|
||||
* uri.
|
||||
*
|
||||
* 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 mixed $calendarId
|
||||
* @param string $objectUri
|
||||
* @return array|null
|
||||
*/
|
||||
public function getCalendarObject($calendarId,$objectUri);
|
||||
|
||||
/**
|
||||
* Creates a new calendar object.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
public function createCalendarObject($calendarId,$objectUri,$calendarData);
|
||||
|
||||
/**
|
||||
* Updates an existing calendarobject, based on it's uri.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
public function updateCalendarObject($calendarId,$objectUri,$calendarData);
|
||||
|
||||
/**
|
||||
* Deletes an existing calendar object.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param string $objectUri
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCalendarObject($calendarId,$objectUri);
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
* The calendar-query is defined in RFC4791 : CalDAV. Using the
|
||||
* calendar-query it is possible for a client to request a specific set of
|
||||
* object, based on contents of iCalendar properties, date-ranges and
|
||||
* iCalendar component types (VTODO, VEVENT).
|
||||
*
|
||||
* This method should just return a list of (relative) urls that match this
|
||||
* query.
|
||||
*
|
||||
* The list of filters are specified as an array. The exact array is
|
||||
* documented by Sabre\CalDAV\CalendarQueryParser.
|
||||
*
|
||||
* Note that it is extremely likely that getCalendarObject for every path
|
||||
* returned from this method will be called almost immediately after. You
|
||||
* may want to anticipate this to speed up these requests.
|
||||
*
|
||||
* This method provides a default implementation, which parses *all* the
|
||||
* iCalendar objects in the specified calendar.
|
||||
*
|
||||
* This default may well be good enough for personal use, and calendars
|
||||
* that aren't very large. But if you anticipate high usage, big calendars
|
||||
* or high loads, you are strongly adviced to optimize certain paths.
|
||||
*
|
||||
* The best way to do so is override this method and to optimize
|
||||
* specifically for 'common filters'.
|
||||
*
|
||||
* Requests that are extremely common are:
|
||||
* * requests for just VEVENTS
|
||||
* * requests for just VTODO
|
||||
* * requests with a time-range-filter on either VEVENT or VTODO.
|
||||
*
|
||||
* ..and combinations of these requests. It may not be worth it to try to
|
||||
* handle every possible situation and just rely on the (relatively
|
||||
* easy to use) CalendarQueryValidator to handle the rest.
|
||||
*
|
||||
* Note that especially time-range-filters may be difficult to parse. A
|
||||
* time-range filter specified on a VEVENT must for instance also handle
|
||||
* recurrence rules correctly.
|
||||
* A good example of how to interprete all these filters can also simply
|
||||
* be found in Sabre\CalDAV\CalendarQueryFilter. This class is as correct
|
||||
* as possible, so it gives you a good idea on what type of stuff you need
|
||||
* to think of.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param array $filters
|
||||
* @return array
|
||||
*/
|
||||
public function calendarQuery($calendarId, array $filters);
|
||||
|
||||
}
|
47
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/NotificationSupport.php
vendored
Normal file
47
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/NotificationSupport.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Backend;
|
||||
|
||||
/**
|
||||
* Adds caldav notification support to a backend.
|
||||
*
|
||||
* Note: This feature is experimental, and may change in between different
|
||||
* SabreDAV versions.
|
||||
*
|
||||
* Notifications are defined at:
|
||||
* http://svn.calendarserver.org/repository/calendarserver/CalendarServer/trunk/doc/Extensions/caldav-notifications.txt
|
||||
*
|
||||
* These notifications are basically a list of server-generated notifications
|
||||
* displayed to the user. Users can dismiss notifications by deleting them.
|
||||
*
|
||||
* The primary usecase is to allow for calendar-sharing.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface NotificationSupport extends BackendInterface {
|
||||
|
||||
/**
|
||||
* Returns a list of notifications for a given principal url.
|
||||
*
|
||||
* The returned array should only consist of implementations of
|
||||
* \Sabre\CalDAV\Notifications\INotificationType.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @return array
|
||||
*/
|
||||
public function getNotificationsForPrincipal($principalUri);
|
||||
|
||||
/**
|
||||
* This deletes a specific notifcation.
|
||||
*
|
||||
* This may be called by a client once it deems a notification handled.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @param \Sabre\CalDAV\Notifications\INotificationType $notification
|
||||
* @return void
|
||||
*/
|
||||
public function deleteNotification($principalUri, \Sabre\CalDAV\Notifications\INotificationType $notification);
|
||||
|
||||
}
|
691
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/PDO.php
vendored
Normal file
691
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/PDO.php
vendored
Normal file
@ -0,0 +1,691 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Backend;
|
||||
|
||||
use Sabre\VObject;
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* PDO CalDAV backend
|
||||
*
|
||||
* This backend is used to store calendar-data in a PDO database, such as
|
||||
* sqlite or MySQL
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class PDO extends AbstractBackend {
|
||||
|
||||
/**
|
||||
* We need to specify a max date, because we need to stop *somewhere*
|
||||
*
|
||||
* On 32 bit system the maximum for a signed integer is 2147483647, so
|
||||
* MAX_DATE cannot be higher than date('Y-m-d', 2147483647) which results
|
||||
* in 2038-01-19 to avoid problems when the date is converted
|
||||
* to a unix timestamp.
|
||||
*/
|
||||
const MAX_DATE = '2038-01-01';
|
||||
|
||||
/**
|
||||
* pdo
|
||||
*
|
||||
* @var \PDO
|
||||
*/
|
||||
protected $pdo;
|
||||
|
||||
/**
|
||||
* The table name that will be used for calendars
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $calendarTableName;
|
||||
|
||||
/**
|
||||
* The table name that will be used for calendar objects
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $calendarObjectTableName;
|
||||
|
||||
/**
|
||||
* List of CalDAV properties, and how they map to database fieldnames
|
||||
* Add your own properties by simply adding on to this array.
|
||||
*
|
||||
* Note that only string-based properties are supported here.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $propertyMap = array(
|
||||
'{DAV:}displayname' => 'displayname',
|
||||
'{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description',
|
||||
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone',
|
||||
'{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
|
||||
'{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates the backend
|
||||
*
|
||||
* @param \PDO $pdo
|
||||
* @param string $calendarTableName
|
||||
* @param string $calendarObjectTableName
|
||||
*/
|
||||
public function __construct(\PDO $pdo, $calendarTableName = 'calendars', $calendarObjectTableName = 'calendarobjects') {
|
||||
|
||||
$this->pdo = $pdo;
|
||||
$this->calendarTableName = $calendarTableName;
|
||||
$this->calendarObjectTableName = $calendarObjectTableName;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, which the basename of the uri with which the calendar is
|
||||
* accessed.
|
||||
* * 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'.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @return array
|
||||
*/
|
||||
public function getCalendarsForUser($principalUri) {
|
||||
|
||||
$fields = array_values($this->propertyMap);
|
||||
$fields[] = 'id';
|
||||
$fields[] = 'uri';
|
||||
$fields[] = 'ctag';
|
||||
$fields[] = 'components';
|
||||
$fields[] = 'principaluri';
|
||||
$fields[] = 'transparent';
|
||||
|
||||
// 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->execute(array($principalUri));
|
||||
|
||||
$calendars = array();
|
||||
while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
|
||||
$components = array();
|
||||
if ($row['components']) {
|
||||
$components = explode(',',$row['components']);
|
||||
}
|
||||
|
||||
$calendar = array(
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'principaluri' => $row['principaluri'],
|
||||
'{' . CalDAV\Plugin::NS_CALENDARSERVER . '}getctag' => $row['ctag']?$row['ctag']:'0',
|
||||
'{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set' => new CalDAV\Property\SupportedCalendarComponentSet($components),
|
||||
'{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' => new CalDAV\Property\ScheduleCalendarTransp($row['transparent']?'transparent':'opaque'),
|
||||
);
|
||||
|
||||
|
||||
foreach($this->propertyMap as $xmlName=>$dbName) {
|
||||
$calendar[$xmlName] = $row[$dbName];
|
||||
}
|
||||
|
||||
$calendars[] = $calendar;
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
public function createCalendar($principalUri, $calendarUri, array $properties) {
|
||||
|
||||
$fieldNames = array(
|
||||
'principaluri',
|
||||
'uri',
|
||||
'ctag',
|
||||
'transparent',
|
||||
);
|
||||
$values = array(
|
||||
':principaluri' => $principalUri,
|
||||
':uri' => $calendarUri,
|
||||
':ctag' => 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';
|
||||
} else {
|
||||
if (!($properties[$sccs] instanceof CalDAV\Property\SupportedCalendarComponentSet)) {
|
||||
throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Property\SupportedCalendarComponentSet');
|
||||
}
|
||||
$values[':components'] = implode(',',$properties[$sccs]->getValue());
|
||||
}
|
||||
$transp = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp';
|
||||
if (isset($properties[$transp])) {
|
||||
$values[':transparent'] = $properties[$transp]->getValue()==='transparent';
|
||||
}
|
||||
|
||||
foreach($this->propertyMap as $xmlName=>$dbName) {
|
||||
if (isset($properties[$xmlName])) {
|
||||
|
||||
$values[':' . $dbName] = $properties[$xmlName];
|
||||
$fieldNames[] = $dbName;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare("INSERT INTO ".$this->calendarTableName." (".implode(', ', $fieldNames).") VALUES (".implode(', ',array_keys($values)).")");
|
||||
$stmt->execute($values);
|
||||
|
||||
return $this->pdo->lastInsertId();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates properties for a calendar.
|
||||
*
|
||||
* The mutations array uses the propertyName in clark-notation as key,
|
||||
* and the array value for the property value. In the case a property
|
||||
* should be deleted, the property value will be null.
|
||||
*
|
||||
* This method must be atomic. If one property cannot be changed, the
|
||||
* entire operation must fail.
|
||||
*
|
||||
* If the operation was successful, true can be returned.
|
||||
* If the operation failed, false can be returned.
|
||||
*
|
||||
* Deletion of a non-existent property is always successful.
|
||||
*
|
||||
* Lastly, it is optional to return detailed information about any
|
||||
* failures. In this case an array should be returned with the following
|
||||
* structure:
|
||||
*
|
||||
* array(
|
||||
* 403 => array(
|
||||
* '{DAV:}displayname' => null,
|
||||
* ),
|
||||
* 424 => array(
|
||||
* '{DAV:}owner' => null,
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* In this example it was forbidden to update {DAV:}displayname.
|
||||
* (403 Forbidden), which in turn also caused {DAV:}owner to fail
|
||||
* (424 Failed Dependency) because the request needs to be atomic.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param array $mutations
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateCalendar($calendarId, array $mutations) {
|
||||
|
||||
$newValues = array();
|
||||
$result = array(
|
||||
200 => array(), // Ok
|
||||
403 => array(), // Forbidden
|
||||
424 => array(), // Failed Dependency
|
||||
);
|
||||
|
||||
$hasError = false;
|
||||
|
||||
foreach($mutations as $propertyName=>$propertyValue) {
|
||||
|
||||
switch($propertyName) {
|
||||
case '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp' :
|
||||
$fieldName = 'transparent';
|
||||
$newValues[$fieldName] = $propertyValue->getValue()==='transparent';
|
||||
break;
|
||||
default :
|
||||
// Checking the property map
|
||||
if (!isset($this->propertyMap[$propertyName])) {
|
||||
// We don't know about this property.
|
||||
$hasError = true;
|
||||
$result[403][$propertyName] = null;
|
||||
unset($mutations[$propertyName]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$fieldName = $this->propertyMap[$propertyName];
|
||||
$newValues[$fieldName] = $propertyValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If there were any errors we need to fail the request
|
||||
if ($hasError) {
|
||||
// Properties has the remaining properties
|
||||
foreach($mutations as $propertyName=>$propertyValue) {
|
||||
$result[424][$propertyName] = null;
|
||||
}
|
||||
|
||||
// Removing unused statuscodes for cleanliness
|
||||
foreach($result as $status=>$properties) {
|
||||
if (is_array($properties) && count($properties)===0) unset($result[$status]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
// Success
|
||||
|
||||
// Now we're generating the sql query.
|
||||
$valuesSql = array();
|
||||
foreach($newValues as $fieldName=>$value) {
|
||||
$valuesSql[] = $fieldName . ' = ?';
|
||||
}
|
||||
$valuesSql[] = 'ctag = ctag + 1';
|
||||
|
||||
$stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ',$valuesSql) . " WHERE id = ?");
|
||||
$newValues['id'] = $calendarId;
|
||||
$stmt->execute(array_values($newValues));
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a calendar and all it's objects
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCalendar($calendarId) {
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
|
||||
$stmt->execute(array($calendarId));
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarTableName.' WHERE id = ?');
|
||||
$stmt->execute(array($calendarId));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all calendar objects within a calendar.
|
||||
*
|
||||
* Every item contains an array with the following keys:
|
||||
* * id - unique identifier which will be used for subsequent updates
|
||||
* * calendardata - The iCalendar-compatible calendar data
|
||||
* * uri - a unique key which will be used to construct the uri. This can be any arbitrary string.
|
||||
* * lastmodified - a timestamp of the last modification time
|
||||
* * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
|
||||
* ' "abcdef"')
|
||||
* * calendarid - The calendarid as it was passed to this function.
|
||||
* * size - The size of the calendar objects, in bytes.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
public function getCalendarObjects($calendarId) {
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size FROM '.$this->calendarObjectTableName.' WHERE calendarid = ?');
|
||||
$stmt->execute(array($calendarId));
|
||||
|
||||
$result = array();
|
||||
foreach($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
|
||||
$result[] = array(
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'lastmodified' => $row['lastmodified'],
|
||||
'etag' => '"' . $row['etag'] . '"',
|
||||
'calendarid' => $row['calendarid'],
|
||||
'size' => (int)$row['size'],
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information from a single calendar object, based on it's object
|
||||
* uri.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
public function getCalendarObject($calendarId,$objectUri) {
|
||||
|
||||
$stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, calendarid, size, calendardata FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute(array($calendarId, $objectUri));
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if(!$row) return null;
|
||||
|
||||
return array(
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'lastmodified' => $row['lastmodified'],
|
||||
'etag' => '"' . $row['etag'] . '"',
|
||||
'calendarid' => $row['calendarid'],
|
||||
'size' => (int)$row['size'],
|
||||
'calendardata' => $row['calendardata'],
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new calendar object.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
public function createCalendarObject($calendarId,$objectUri,$calendarData) {
|
||||
|
||||
$extraData = $this->getDenormalizedData($calendarData);
|
||||
|
||||
$stmt = $this->pdo->prepare('INSERT INTO '.$this->calendarObjectTableName.' (calendarid, uri, calendardata, lastmodified, etag, size, componenttype, firstoccurence, lastoccurence) VALUES (?,?,?,?,?,?,?,?,?)');
|
||||
$stmt->execute(array(
|
||||
$calendarId,
|
||||
$objectUri,
|
||||
$calendarData,
|
||||
time(),
|
||||
$extraData['etag'],
|
||||
$extraData['size'],
|
||||
$extraData['componentType'],
|
||||
$extraData['firstOccurence'],
|
||||
$extraData['lastOccurence'],
|
||||
));
|
||||
$stmt = $this->pdo->prepare('UPDATE '.$this->calendarTableName.' SET ctag = ctag + 1 WHERE id = ?');
|
||||
$stmt->execute(array($calendarId));
|
||||
|
||||
return '"' . $extraData['etag'] . '"';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing calendarobject, based on it's uri.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
public function updateCalendarObject($calendarId,$objectUri,$calendarData) {
|
||||
|
||||
$extraData = $this->getDenormalizedData($calendarData);
|
||||
|
||||
$stmt = $this->pdo->prepare('UPDATE '.$this->calendarObjectTableName.' SET calendardata = ?, lastmodified = ?, etag = ?, size = ?, componenttype = ?, firstoccurence = ?, lastoccurence = ? WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute(array($calendarData,time(), $extraData['etag'], $extraData['size'], $extraData['componentType'], $extraData['firstOccurence'], $extraData['lastOccurence'] ,$calendarId,$objectUri));
|
||||
$stmt = $this->pdo->prepare('UPDATE '.$this->calendarTableName.' SET ctag = ctag + 1 WHERE id = ?');
|
||||
$stmt->execute(array($calendarId));
|
||||
|
||||
return '"' . $extraData['etag'] . '"';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses some information from calendar objects, used for optimized
|
||||
* calendar-queries.
|
||||
*
|
||||
* Returns an array with the following keys:
|
||||
* * etag
|
||||
* * size
|
||||
* * componentType
|
||||
* * firstOccurence
|
||||
* * lastOccurence
|
||||
*
|
||||
* @param string $calendarData
|
||||
* @return array
|
||||
*/
|
||||
protected function getDenormalizedData($calendarData) {
|
||||
|
||||
$vObject = VObject\Reader::read($calendarData);
|
||||
$componentType = null;
|
||||
$component = null;
|
||||
$firstOccurence = null;
|
||||
$lastOccurence = null;
|
||||
foreach($vObject->getComponents() as $component) {
|
||||
if ($component->name!=='VTIMEZONE') {
|
||||
$componentType = $component->name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$componentType) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
|
||||
}
|
||||
if ($componentType === 'VEVENT') {
|
||||
$firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
|
||||
// Finding the last occurence is a bit harder
|
||||
if (!isset($component->RRULE)) {
|
||||
if (isset($component->DTEND)) {
|
||||
$lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
|
||||
} elseif (isset($component->DURATION)) {
|
||||
$endDate = clone $component->DTSTART->getDateTime();
|
||||
$endDate->add(VObject\DateTimeParser::parse($component->DURATION->getValue()));
|
||||
$lastOccurence = $endDate->getTimeStamp();
|
||||
} elseif (!$component->DTSTART->hasTime()) {
|
||||
$endDate = clone $component->DTSTART->getDateTime();
|
||||
$endDate->modify('+1 day');
|
||||
$lastOccurence = $endDate->getTimeStamp();
|
||||
} else {
|
||||
$lastOccurence = $firstOccurence;
|
||||
}
|
||||
} else {
|
||||
$it = new VObject\RecurrenceIterator($vObject, (string)$component->UID);
|
||||
$maxDate = new \DateTime(self::MAX_DATE);
|
||||
if ($it->isInfinite()) {
|
||||
$lastOccurence = $maxDate->getTimeStamp();
|
||||
} else {
|
||||
$end = $it->getDtEnd();
|
||||
while($it->valid() && $end < $maxDate) {
|
||||
$end = $it->getDtEnd();
|
||||
$it->next();
|
||||
|
||||
}
|
||||
$lastOccurence = $end->getTimeStamp();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'etag' => md5($calendarData),
|
||||
'size' => strlen($calendarData),
|
||||
'componentType' => $componentType,
|
||||
'firstOccurence' => $firstOccurence,
|
||||
'lastOccurence' => $lastOccurence,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing calendar object.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param string $objectUri
|
||||
* @return void
|
||||
*/
|
||||
public function deleteCalendarObject($calendarId,$objectUri) {
|
||||
|
||||
$stmt = $this->pdo->prepare('DELETE FROM '.$this->calendarObjectTableName.' WHERE calendarid = ? AND uri = ?');
|
||||
$stmt->execute(array($calendarId,$objectUri));
|
||||
$stmt = $this->pdo->prepare('UPDATE '. $this->calendarTableName .' SET ctag = ctag + 1 WHERE id = ?');
|
||||
$stmt->execute(array($calendarId));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
* The calendar-query is defined in RFC4791 : CalDAV. Using the
|
||||
* calendar-query it is possible for a client to request a specific set of
|
||||
* object, based on contents of iCalendar properties, date-ranges and
|
||||
* iCalendar component types (VTODO, VEVENT).
|
||||
*
|
||||
* This method should just return a list of (relative) urls that match this
|
||||
* query.
|
||||
*
|
||||
* The list of filters are specified as an array. The exact array is
|
||||
* documented by \Sabre\CalDAV\CalendarQueryParser.
|
||||
*
|
||||
* Note that it is extremely likely that getCalendarObject for every path
|
||||
* returned from this method will be called almost immediately after. You
|
||||
* may want to anticipate this to speed up these requests.
|
||||
*
|
||||
* This method provides a default implementation, which parses *all* the
|
||||
* iCalendar objects in the specified calendar.
|
||||
*
|
||||
* This default may well be good enough for personal use, and calendars
|
||||
* that aren't very large. But if you anticipate high usage, big calendars
|
||||
* or high loads, you are strongly adviced to optimize certain paths.
|
||||
*
|
||||
* The best way to do so is override this method and to optimize
|
||||
* specifically for 'common filters'.
|
||||
*
|
||||
* Requests that are extremely common are:
|
||||
* * requests for just VEVENTS
|
||||
* * requests for just VTODO
|
||||
* * requests with a time-range-filter on a VEVENT.
|
||||
*
|
||||
* ..and combinations of these requests. It may not be worth it to try to
|
||||
* handle every possible situation and just rely on the (relatively
|
||||
* easy to use) CalendarQueryValidator to handle the rest.
|
||||
*
|
||||
* Note that especially time-range-filters may be difficult to parse. A
|
||||
* time-range filter specified on a VEVENT must for instance also handle
|
||||
* recurrence rules correctly.
|
||||
* A good example of how to interprete all these filters can also simply
|
||||
* be found in \Sabre\CalDAV\CalendarQueryFilter. This class is as correct
|
||||
* as possible, so it gives you a good idea on what type of stuff you need
|
||||
* to think of.
|
||||
*
|
||||
* This specific implementation (for the PDO) backend optimizes filters on
|
||||
* specific components, and VEVENT time-ranges.
|
||||
*
|
||||
* @param string $calendarId
|
||||
* @param array $filters
|
||||
* @return array
|
||||
*/
|
||||
public function calendarQuery($calendarId, array $filters) {
|
||||
|
||||
$result = array();
|
||||
$validator = new \Sabre\CalDAV\CalendarQueryValidator();
|
||||
|
||||
$componentType = null;
|
||||
$requirePostFilter = true;
|
||||
$timeRange = null;
|
||||
|
||||
// if no filters were specified, we don't need to filter after a query
|
||||
if (!$filters['prop-filters'] && !$filters['comp-filters']) {
|
||||
$requirePostFilter = false;
|
||||
}
|
||||
|
||||
// Figuring out if there's a component filter
|
||||
if (count($filters['comp-filters']) > 0 && !$filters['comp-filters'][0]['is-not-defined']) {
|
||||
$componentType = $filters['comp-filters'][0]['name'];
|
||||
|
||||
// Checking if we need post-filters
|
||||
if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['time-range'] && !$filters['comp-filters'][0]['prop-filters']) {
|
||||
$requirePostFilter = false;
|
||||
}
|
||||
// There was a time-range filter
|
||||
if ($componentType == 'VEVENT' && isset($filters['comp-filters'][0]['time-range'])) {
|
||||
$timeRange = $filters['comp-filters'][0]['time-range'];
|
||||
|
||||
// If start time OR the end time is not specified, we can do a
|
||||
// 100% accurate mysql query.
|
||||
if (!$filters['prop-filters'] && !$filters['comp-filters'][0]['comp-filters'] && !$filters['comp-filters'][0]['prop-filters'] && (!$timeRange['start'] || !$timeRange['end'])) {
|
||||
$requirePostFilter = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($requirePostFilter) {
|
||||
$query = "SELECT uri, calendardata FROM ".$this->calendarObjectTableName." WHERE calendarid = :calendarid";
|
||||
} else {
|
||||
$query = "SELECT uri FROM ".$this->calendarObjectTableName." WHERE calendarid = :calendarid";
|
||||
}
|
||||
|
||||
$values = array(
|
||||
'calendarid' => $calendarId,
|
||||
);
|
||||
|
||||
if ($componentType) {
|
||||
$query.=" AND componenttype = :componenttype";
|
||||
$values['componenttype'] = $componentType;
|
||||
}
|
||||
|
||||
if ($timeRange && $timeRange['start']) {
|
||||
$query.=" AND lastoccurence > :startdate";
|
||||
$values['startdate'] = $timeRange['start']->getTimeStamp();
|
||||
}
|
||||
if ($timeRange && $timeRange['end']) {
|
||||
$query.=" AND firstoccurence < :enddate";
|
||||
$values['enddate'] = $timeRange['end']->getTimeStamp();
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare($query);
|
||||
$stmt->execute($values);
|
||||
|
||||
$result = array();
|
||||
while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
if ($requirePostFilter) {
|
||||
if (!$this->validateFilterForObject($row, $filters)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$result[] = $row['uri'];
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
}
|
243
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/SharingSupport.php
vendored
Normal file
243
vendor/sabre/dav/lib/Sabre/CalDAV/Backend/SharingSupport.php
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
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.
|
||||
*
|
||||
* 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\Invite
|
||||
*
|
||||
*
|
||||
* 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 getCalendarsForPrincipal.
|
||||
*
|
||||
* {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
|
||||
* getCalendarsByUser, 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.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface SharingSupport extends NotificationSupport {
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return void
|
||||
*/
|
||||
function updateShares($calendarId, array $add, array $remove);
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @return array
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Publishes a calendar
|
||||
*
|
||||
* @param mixed $calendarId
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
function setPublishStatus($calendarId, $value);
|
||||
|
||||
}
|
376
vendor/sabre/dav/lib/Sabre/CalDAV/Calendar.php
vendored
Normal file
376
vendor/sabre/dav/lib/Sabre/CalDAV/Calendar.php
vendored
Normal file
@ -0,0 +1,376 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\DAVACL;
|
||||
|
||||
/**
|
||||
* This object represents a CalDAV calendar.
|
||||
*
|
||||
* A calendar can contain multiple TODO and or Events. These are represented
|
||||
* as \Sabre\CalDAV\CalendarObject objects.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Calendar implements ICalendar, DAV\IProperties, DAVACL\IACL {
|
||||
|
||||
/**
|
||||
* This is an array with calendar information
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $calendarInfo;
|
||||
|
||||
/**
|
||||
* CalDAV backend
|
||||
*
|
||||
* @var Backend\BackendInterface
|
||||
*/
|
||||
protected $caldavBackend;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Backend\BackendInterface $caldavBackend
|
||||
* @param array $calendarInfo
|
||||
*/
|
||||
public function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) {
|
||||
|
||||
$this->caldavBackend = $caldavBackend;
|
||||
$this->calendarInfo = $calendarInfo;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the calendar
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return $this->calendarInfo['uri'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates properties such as the display name and description
|
||||
*
|
||||
* @param array $mutations
|
||||
* @return array
|
||||
*/
|
||||
public function updateProperties($mutations) {
|
||||
|
||||
return $this->caldavBackend->updateCalendar($this->calendarInfo['id'],$mutations);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of properties
|
||||
*
|
||||
* @param array $requestedProperties
|
||||
* @return array
|
||||
*/
|
||||
public function getProperties($requestedProperties) {
|
||||
|
||||
$response = array();
|
||||
|
||||
foreach($requestedProperties as $prop) switch($prop) {
|
||||
|
||||
case '{urn:ietf:params:xml:ns:caldav}supported-calendar-data' :
|
||||
$response[$prop] = new Property\SupportedCalendarData();
|
||||
break;
|
||||
case '{urn:ietf:params:xml:ns:caldav}supported-collation-set' :
|
||||
$response[$prop] = new Property\SupportedCollationSet();
|
||||
break;
|
||||
case '{DAV:}owner' :
|
||||
$response[$prop] = new DAVACL\Property\Principal(DAVACL\Property\Principal::HREF,$this->calendarInfo['principaluri']);
|
||||
break;
|
||||
default :
|
||||
if (isset($this->calendarInfo[$prop])) $response[$prop] = $this->calendarInfo[$prop];
|
||||
break;
|
||||
|
||||
}
|
||||
return $response;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a calendar object
|
||||
*
|
||||
* The contained calendar objects are for example Events or Todo's.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Sabre\CalDAV\ICalendarObject
|
||||
*/
|
||||
public function getChild($name) {
|
||||
|
||||
$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name);
|
||||
|
||||
if (!$obj) throw new DAV\Exception\NotFound('Calendar object not found');
|
||||
|
||||
$obj['acl'] = $this->getACL();
|
||||
// Removing the irrelivant
|
||||
foreach($obj['acl'] as $key=>$acl) {
|
||||
if ($acl['privilege'] === '{' . Plugin::NS_CALDAV . '}read-free-busy') {
|
||||
unset($obj['acl'][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return new CalendarObject($this->caldavBackend,$this->calendarInfo,$obj);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full list of calendar objects
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getChildren() {
|
||||
|
||||
$objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
|
||||
$children = array();
|
||||
foreach($objs as $obj) {
|
||||
$obj['acl'] = $this->getACL();
|
||||
// Removing the irrelivant
|
||||
foreach($obj['acl'] as $key=>$acl) {
|
||||
if ($acl['privilege'] === '{' . Plugin::NS_CALDAV . '}read-free-busy') {
|
||||
unset($obj['acl'][$key]);
|
||||
}
|
||||
}
|
||||
$children[] = new CalendarObject($this->caldavBackend,$this->calendarInfo,$obj);
|
||||
}
|
||||
return $children;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a child-node exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function childExists($name) {
|
||||
|
||||
$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'],$name);
|
||||
if (!$obj)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new directory
|
||||
*
|
||||
* We actually block this, as subdirectories are not allowed in calendars.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function createDirectory($name) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file
|
||||
*
|
||||
* The contents of the new file must be a valid ICalendar string.
|
||||
*
|
||||
* @param string $name
|
||||
* @param resource $calendarData
|
||||
* @return string|null
|
||||
*/
|
||||
public function createFile($name,$calendarData = null) {
|
||||
|
||||
if (is_resource($calendarData)) {
|
||||
$calendarData = stream_get_contents($calendarData);
|
||||
}
|
||||
return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'],$name,$calendarData);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the calendar.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete() {
|
||||
|
||||
$this->caldavBackend->deleteCalendar($this->calendarInfo['id']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames the calendar. Note that most calendars use the
|
||||
* {DAV:}displayname to display a name to display a name.
|
||||
*
|
||||
* @param string $newName
|
||||
* @return void
|
||||
*/
|
||||
public function setName($newName) {
|
||||
|
||||
throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification date as a unix timestamp.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getLastModified() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner() {
|
||||
|
||||
return $this->calendarInfo['principaluri'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getACL() {
|
||||
|
||||
return array(
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->getOwner(),
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->getOwner() . '/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy',
|
||||
'principal' => '{DAV:}authenticated',
|
||||
'protected' => true,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public 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'][] = array(
|
||||
'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy',
|
||||
);
|
||||
|
||||
}
|
||||
return $default;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
* The calendar-query is defined in RFC4791 : CalDAV. Using the
|
||||
* calendar-query it is possible for a client to request a specific set of
|
||||
* object, based on contents of iCalendar properties, date-ranges and
|
||||
* iCalendar component types (VTODO, VEVENT).
|
||||
*
|
||||
* This method should just return a list of (relative) urls that match this
|
||||
* query.
|
||||
*
|
||||
* The list of filters are specified as an array. The exact array is
|
||||
* documented by Sabre\CalDAV\CalendarQueryParser.
|
||||
*
|
||||
* @param array $filters
|
||||
* @return array
|
||||
*/
|
||||
public function calendarQuery(array $filters) {
|
||||
|
||||
return $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
|
||||
|
||||
}
|
||||
|
||||
}
|
279
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarObject.php
vendored
Normal file
279
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarObject.php
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* The CalendarObject represents a single VEVENT or VTODO within a Calendar.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\DAVACL\IACL {
|
||||
|
||||
/**
|
||||
* Sabre\CalDAV\Backend\BackendInterface
|
||||
*
|
||||
* @var Sabre\CalDAV\Backend\AbstractBackend
|
||||
*/
|
||||
protected $caldavBackend;
|
||||
|
||||
/**
|
||||
* Array with information about this CalendarObject
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $objectData;
|
||||
|
||||
/**
|
||||
* Array with information about the containing calendar
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $calendarInfo;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Backend\BackendInterface $caldavBackend
|
||||
* @param array $calendarInfo
|
||||
* @param array $objectData
|
||||
*/
|
||||
public function __construct(Backend\BackendInterface $caldavBackend,array $calendarInfo,array $objectData) {
|
||||
|
||||
$this->caldavBackend = $caldavBackend;
|
||||
|
||||
if (!isset($objectData['calendarid'])) {
|
||||
throw new \InvalidArgumentException('The objectData argument must contain a \'calendarid\' property');
|
||||
}
|
||||
if (!isset($objectData['uri'])) {
|
||||
throw new \InvalidArgumentException('The objectData argument must contain an \'uri\' property');
|
||||
}
|
||||
|
||||
$this->calendarInfo = $calendarInfo;
|
||||
$this->objectData = $objectData;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the uri for this object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return $this->objectData['uri'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ICalendar-formatted object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get() {
|
||||
|
||||
// Pre-populating the 'calendardata' is optional, if we don't have it
|
||||
// already we fetch it from the backend.
|
||||
if (!isset($this->objectData['calendardata'])) {
|
||||
$this->objectData = $this->caldavBackend->getCalendarObject($this->objectData['calendarid'], $this->objectData['uri']);
|
||||
}
|
||||
return $this->objectData['calendardata'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ICalendar-formatted object
|
||||
*
|
||||
* @param string|resource $calendarData
|
||||
* @return string
|
||||
*/
|
||||
public function put($calendarData) {
|
||||
|
||||
if (is_resource($calendarData)) {
|
||||
$calendarData = stream_get_contents($calendarData);
|
||||
}
|
||||
$etag = $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'],$this->objectData['uri'],$calendarData);
|
||||
$this->objectData['calendardata'] = $calendarData;
|
||||
$this->objectData['etag'] = $etag;
|
||||
|
||||
return $etag;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the calendar object
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete() {
|
||||
|
||||
$this->caldavBackend->deleteCalendarObject($this->calendarInfo['id'],$this->objectData['uri']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mime content-type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType() {
|
||||
|
||||
return 'text/calendar; charset=utf-8';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ETag for this object.
|
||||
*
|
||||
* The ETag is an arbitrary string, but MUST be surrounded by double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getETag() {
|
||||
|
||||
if (isset($this->objectData['etag'])) {
|
||||
return $this->objectData['etag'];
|
||||
} else {
|
||||
return '"' . md5($this->get()). '"';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification date as a unix timestamp
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastModified() {
|
||||
|
||||
return $this->objectData['lastmodified'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of this object in bytes
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSize() {
|
||||
|
||||
if (array_key_exists('size',$this->objectData)) {
|
||||
return $this->objectData['size'];
|
||||
} else {
|
||||
return strlen($this->get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner() {
|
||||
|
||||
return $this->calendarInfo['principaluri'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getACL() {
|
||||
|
||||
// An alternative acl may be specified in the object data.
|
||||
if (isset($this->objectData['acl'])) {
|
||||
return $this->objectData['acl'];
|
||||
}
|
||||
|
||||
// The default ACL
|
||||
return array(
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @return void
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
298
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarQueryParser.php
vendored
Normal file
298
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarQueryParser.php
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\VObject;
|
||||
|
||||
/**
|
||||
* Parses the calendar-query report request body.
|
||||
*
|
||||
* Whoever designed this format, and the CalDAV equivalent even more so,
|
||||
* has no feel for design.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class CalendarQueryParser {
|
||||
|
||||
/**
|
||||
* List of requested properties the client wanted
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $requestedProperties;
|
||||
|
||||
/**
|
||||
* List of property/component filters.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $filters;
|
||||
|
||||
/**
|
||||
* This property will contain null if CALDAV:expand was not specified,
|
||||
* otherwise it will contain an array with 2 elements (start, end). Each
|
||||
* contain a DateTime object.
|
||||
*
|
||||
* If expand is specified, recurring calendar objects are to be expanded
|
||||
* into their individual components, and only the components that fall
|
||||
* within the specified time-range are to be returned.
|
||||
*
|
||||
* For more details, see rfc4791, section 9.6.5.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
public $expand;
|
||||
|
||||
/**
|
||||
* DOM Document
|
||||
*
|
||||
* @var DOMDocument
|
||||
*/
|
||||
protected $dom;
|
||||
|
||||
/**
|
||||
* DOM XPath object
|
||||
*
|
||||
* @var DOMXPath
|
||||
*/
|
||||
protected $xpath;
|
||||
|
||||
/**
|
||||
* Creates the parser
|
||||
*
|
||||
* @param \DOMDocument $dom
|
||||
*/
|
||||
public function __construct(\DOMDocument $dom) {
|
||||
|
||||
$this->dom = $dom;
|
||||
$this->xpath = new \DOMXPath($dom);
|
||||
$this->xpath->registerNameSpace('cal',Plugin::NS_CALDAV);
|
||||
$this->xpath->registerNameSpace('dav','urn:DAV');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the request.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function parse() {
|
||||
|
||||
$filterNode = null;
|
||||
|
||||
$filter = $this->xpath->query('/cal:calendar-query/cal:filter');
|
||||
if ($filter->length !== 1) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('Only one filter element is allowed');
|
||||
}
|
||||
|
||||
$compFilters = $this->parseCompFilters($filter->item(0));
|
||||
if (count($compFilters)!==1) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('There must be exactly 1 top-level comp-filter.');
|
||||
}
|
||||
|
||||
$this->filters = $compFilters[0];
|
||||
$this->requestedProperties = array_keys(\Sabre\DAV\XMLUtil::parseProperties($this->dom->firstChild));
|
||||
|
||||
$expand = $this->xpath->query('/cal:calendar-query/dav:prop/cal:calendar-data/cal:expand');
|
||||
if ($expand->length>0) {
|
||||
$this->expand = $this->parseExpand($expand->item(0));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses all the 'comp-filter' elements from a node
|
||||
*
|
||||
* @param \DOMElement $parentNode
|
||||
* @return array
|
||||
*/
|
||||
protected function parseCompFilters(\DOMElement $parentNode) {
|
||||
|
||||
$compFilterNodes = $this->xpath->query('cal:comp-filter', $parentNode);
|
||||
$result = array();
|
||||
|
||||
for($ii=0; $ii < $compFilterNodes->length; $ii++) {
|
||||
|
||||
$compFilterNode = $compFilterNodes->item($ii);
|
||||
|
||||
$compFilter = array();
|
||||
$compFilter['name'] = $compFilterNode->getAttribute('name');
|
||||
$compFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $compFilterNode)->length>0;
|
||||
$compFilter['comp-filters'] = $this->parseCompFilters($compFilterNode);
|
||||
$compFilter['prop-filters'] = $this->parsePropFilters($compFilterNode);
|
||||
$compFilter['time-range'] = $this->parseTimeRange($compFilterNode);
|
||||
|
||||
if ($compFilter['time-range'] && !in_array($compFilter['name'],array(
|
||||
'VEVENT',
|
||||
'VTODO',
|
||||
'VJOURNAL',
|
||||
'VFREEBUSY',
|
||||
'VALARM',
|
||||
))) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('The time-range filter is not defined for the ' . $compFilter['name'] . ' component');
|
||||
};
|
||||
|
||||
$result[] = $compFilter;
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses all the prop-filter elements from a node
|
||||
*
|
||||
* @param \DOMElement $parentNode
|
||||
* @return array
|
||||
*/
|
||||
protected function parsePropFilters(\DOMElement $parentNode) {
|
||||
|
||||
$propFilterNodes = $this->xpath->query('cal:prop-filter', $parentNode);
|
||||
$result = array();
|
||||
|
||||
for ($ii=0; $ii < $propFilterNodes->length; $ii++) {
|
||||
|
||||
$propFilterNode = $propFilterNodes->item($ii);
|
||||
$propFilter = array();
|
||||
$propFilter['name'] = $propFilterNode->getAttribute('name');
|
||||
$propFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $propFilterNode)->length>0;
|
||||
$propFilter['param-filters'] = $this->parseParamFilters($propFilterNode);
|
||||
$propFilter['text-match'] = $this->parseTextMatch($propFilterNode);
|
||||
$propFilter['time-range'] = $this->parseTimeRange($propFilterNode);
|
||||
|
||||
$result[] = $propFilter;
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the param-filter element
|
||||
*
|
||||
* @param \DOMElement $parentNode
|
||||
* @return array
|
||||
*/
|
||||
protected function parseParamFilters(\DOMElement $parentNode) {
|
||||
|
||||
$paramFilterNodes = $this->xpath->query('cal:param-filter', $parentNode);
|
||||
$result = array();
|
||||
|
||||
for($ii=0;$ii<$paramFilterNodes->length;$ii++) {
|
||||
|
||||
$paramFilterNode = $paramFilterNodes->item($ii);
|
||||
$paramFilter = array();
|
||||
$paramFilter['name'] = $paramFilterNode->getAttribute('name');
|
||||
$paramFilter['is-not-defined'] = $this->xpath->query('cal:is-not-defined', $paramFilterNode)->length>0;
|
||||
$paramFilter['text-match'] = $this->parseTextMatch($paramFilterNode);
|
||||
|
||||
$result[] = $paramFilter;
|
||||
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the text-match element
|
||||
*
|
||||
* @param \DOMElement $parentNode
|
||||
* @return array|null
|
||||
*/
|
||||
protected function parseTextMatch(\DOMElement $parentNode) {
|
||||
|
||||
$textMatchNodes = $this->xpath->query('cal:text-match', $parentNode);
|
||||
|
||||
if ($textMatchNodes->length === 0)
|
||||
return null;
|
||||
|
||||
$textMatchNode = $textMatchNodes->item(0);
|
||||
$negateCondition = $textMatchNode->getAttribute('negate-condition');
|
||||
$negateCondition = $negateCondition==='yes';
|
||||
$collation = $textMatchNode->getAttribute('collation');
|
||||
if (!$collation) $collation = 'i;ascii-casemap';
|
||||
|
||||
return array(
|
||||
'negate-condition' => $negateCondition,
|
||||
'collation' => $collation,
|
||||
'value' => $textMatchNode->nodeValue
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the time-range element
|
||||
*
|
||||
* @param \DOMElement $parentNode
|
||||
* @return array|null
|
||||
*/
|
||||
protected function parseTimeRange(\DOMElement $parentNode) {
|
||||
|
||||
$timeRangeNodes = $this->xpath->query('cal:time-range', $parentNode);
|
||||
if ($timeRangeNodes->length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$timeRangeNode = $timeRangeNodes->item(0);
|
||||
|
||||
if ($start = $timeRangeNode->getAttribute('start')) {
|
||||
$start = VObject\DateTimeParser::parseDateTime($start);
|
||||
} else {
|
||||
$start = null;
|
||||
}
|
||||
if ($end = $timeRangeNode->getAttribute('end')) {
|
||||
$end = VObject\DateTimeParser::parseDateTime($end);
|
||||
} else {
|
||||
$end = null;
|
||||
}
|
||||
|
||||
if (!is_null($start) && !is_null($end) && $end <= $start) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('The end-date must be larger than the start-date in the time-range filter');
|
||||
}
|
||||
|
||||
return array(
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the CALDAV:expand element
|
||||
*
|
||||
* @param \DOMElement $parentNode
|
||||
* @return void
|
||||
*/
|
||||
protected function parseExpand(\DOMElement $parentNode) {
|
||||
|
||||
$start = $parentNode->getAttribute('start');
|
||||
if(!$start) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('The "start" attribute is required for the CALDAV:expand element');
|
||||
}
|
||||
$start = VObject\DateTimeParser::parseDateTime($start);
|
||||
|
||||
$end = $parentNode->getAttribute('end');
|
||||
if(!$end) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('The "end" attribute is required for the CALDAV:expand element');
|
||||
}
|
||||
|
||||
$end = VObject\DateTimeParser::parseDateTime($end);
|
||||
|
||||
if ($end <= $start) {
|
||||
throw new \Sabre\DAV\Exception\BadRequest('The end-date must be larger than the start-date in the expand element.');
|
||||
}
|
||||
|
||||
return array(
|
||||
'start' => $start,
|
||||
'end' => $end,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
392
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarQueryValidator.php
vendored
Normal file
392
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarQueryValidator.php
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\VObject;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* CalendarQuery Validator
|
||||
*
|
||||
* This class is responsible for checking if an iCalendar object matches a set
|
||||
* of filters. The main function to do this is 'validate'.
|
||||
*
|
||||
* This is used to determine which icalendar objects should be returned for a
|
||||
* calendar-query REPORT request.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class CalendarQueryValidator {
|
||||
|
||||
/**
|
||||
* Verify if a list of filters applies to the calendar data object
|
||||
*
|
||||
* The list of filters must be formatted as parsed by \Sabre\CalDAV\CalendarQueryParser
|
||||
*
|
||||
* @param VObject\Component $vObject
|
||||
* @param array $filters
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(VObject\Component $vObject,array $filters) {
|
||||
|
||||
// The top level object is always a component filter.
|
||||
// We'll parse it manually, as it's pretty simple.
|
||||
if ($vObject->name !== $filters['name']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
$this->validateCompFilters($vObject, $filters['comp-filters']) &&
|
||||
$this->validatePropFilters($vObject, $filters['prop-filters']);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks the validity of comp-filters.
|
||||
*
|
||||
* A list of comp-filters needs to be specified. Also the parent of the
|
||||
* component we're checking should be specified, not the component to check
|
||||
* itself.
|
||||
*
|
||||
* @param VObject\Component $parent
|
||||
* @param array $filters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateCompFilters(VObject\Component $parent, array $filters) {
|
||||
|
||||
foreach($filters as $filter) {
|
||||
|
||||
$isDefined = isset($parent->$filter['name']);
|
||||
|
||||
if ($filter['is-not-defined']) {
|
||||
|
||||
if ($isDefined) {
|
||||
return false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!$isDefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($filter['time-range']) {
|
||||
foreach($parent->$filter['name'] as $subComponent) {
|
||||
if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$filter['comp-filters'] && !$filter['prop-filters']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there are sub-filters, we need to find at least one component
|
||||
// for which the subfilters hold true.
|
||||
foreach($parent->$filter['name'] as $subComponent) {
|
||||
|
||||
if (
|
||||
$this->validateCompFilters($subComponent, $filter['comp-filters']) &&
|
||||
$this->validatePropFilters($subComponent, $filter['prop-filters'])) {
|
||||
// We had a match, so this comp-filter succeeds
|
||||
continue 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we got here it means there were sub-comp-filters or
|
||||
// sub-prop-filters and there was no match. This means this filter
|
||||
// needs to return false.
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// If we got here it means we got through all comp-filters alive so the
|
||||
// filters were all true.
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks the validity of prop-filters.
|
||||
*
|
||||
* A list of prop-filters needs to be specified. Also the parent of the
|
||||
* property we're checking should be specified, not the property to check
|
||||
* itself.
|
||||
*
|
||||
* @param VObject\Component $parent
|
||||
* @param array $filters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validatePropFilters(VObject\Component $parent, array $filters) {
|
||||
|
||||
foreach($filters as $filter) {
|
||||
|
||||
$isDefined = isset($parent->$filter['name']);
|
||||
|
||||
if ($filter['is-not-defined']) {
|
||||
|
||||
if ($isDefined) {
|
||||
return false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!$isDefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($filter['time-range']) {
|
||||
foreach($parent->$filter['name'] as $subComponent) {
|
||||
if ($this->validateTimeRange($subComponent, $filter['time-range']['start'], $filter['time-range']['end'])) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$filter['param-filters'] && !$filter['text-match']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there are sub-filters, we need to find at least one property
|
||||
// for which the subfilters hold true.
|
||||
foreach($parent->$filter['name'] as $subComponent) {
|
||||
|
||||
if(
|
||||
$this->validateParamFilters($subComponent, $filter['param-filters']) &&
|
||||
(!$filter['text-match'] || $this->validateTextMatch($subComponent, $filter['text-match']))
|
||||
) {
|
||||
// We had a match, so this prop-filter succeeds
|
||||
continue 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we got here it means there were sub-param-filters or
|
||||
// text-match filters and there was no match. This means the
|
||||
// filter needs to return false.
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// If we got here it means we got through all prop-filters alive so the
|
||||
// filters were all true.
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks the validity of param-filters.
|
||||
*
|
||||
* A list of param-filters needs to be specified. Also the parent of the
|
||||
* parameter we're checking should be specified, not the parameter to check
|
||||
* itself.
|
||||
*
|
||||
* @param VObject\Property $parent
|
||||
* @param array $filters
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateParamFilters(VObject\Property $parent, array $filters) {
|
||||
|
||||
foreach($filters as $filter) {
|
||||
|
||||
$isDefined = isset($parent[$filter['name']]);
|
||||
|
||||
if ($filter['is-not-defined']) {
|
||||
|
||||
if ($isDefined) {
|
||||
return false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!$isDefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$filter['text-match']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (version_compare(VObject\Version::VERSION, '3.0.0beta1', '>=')) {
|
||||
|
||||
// If there are sub-filters, we need to find at least one parameter
|
||||
// for which the subfilters hold true.
|
||||
foreach($parent[$filter['name']]->getParts() as $subParam) {
|
||||
|
||||
if($this->validateTextMatch($subParam,$filter['text-match'])) {
|
||||
// We had a match, so this param-filter succeeds
|
||||
continue 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// If there are sub-filters, we need to find at least one parameter
|
||||
// for which the subfilters hold true.
|
||||
foreach($parent[$filter['name']] as $subParam) {
|
||||
|
||||
if($this->validateTextMatch($subParam,$filter['text-match'])) {
|
||||
// We had a match, so this param-filter succeeds
|
||||
continue 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If we got here it means there was a text-match filter and there
|
||||
// were no matches. This means the filter needs to return false.
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// If we got here it means we got through all param-filters alive so the
|
||||
// filters were all true.
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks the validity of a text-match.
|
||||
*
|
||||
* A single text-match should be specified as well as the specific property
|
||||
* or parameter we need to validate.
|
||||
*
|
||||
* @param VObject\Node|string $check Value to check against.
|
||||
* @param array $textMatch
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateTextMatch($check, array $textMatch) {
|
||||
|
||||
if ($check instanceof VObject\Node) {
|
||||
$check = (string)$check;
|
||||
}
|
||||
|
||||
$isMatching = \Sabre\DAV\StringUtil::textMatch($check, $textMatch['value'], $textMatch['collation']);
|
||||
|
||||
return ($textMatch['negate-condition'] xor $isMatching);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates if a component matches the given time range.
|
||||
*
|
||||
* This is all based on the rules specified in rfc4791, which are quite
|
||||
* complex.
|
||||
*
|
||||
* @param VObject\Node $component
|
||||
* @param DateTime $start
|
||||
* @param DateTime $end
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateTimeRange(VObject\Node $component, $start, $end) {
|
||||
|
||||
if (is_null($start)) {
|
||||
$start = new DateTime('1900-01-01');
|
||||
}
|
||||
if (is_null($end)) {
|
||||
$end = new DateTime('3000-01-01');
|
||||
}
|
||||
|
||||
switch($component->name) {
|
||||
|
||||
case 'VEVENT' :
|
||||
case 'VTODO' :
|
||||
case 'VJOURNAL' :
|
||||
|
||||
return $component->isInTimeRange($start, $end);
|
||||
|
||||
case 'VALARM' :
|
||||
|
||||
// If the valarm is wrapped in a recurring event, we need to
|
||||
// expand the recursions, and validate each.
|
||||
//
|
||||
// Our datamodel doesn't easily allow us to do this straight
|
||||
// in the VALARM component code, so this is a hack, and an
|
||||
// expensive one too.
|
||||
if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
|
||||
|
||||
// Fire up the iterator!
|
||||
$it = new VObject\RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
|
||||
while($it->valid()) {
|
||||
$expandedEvent = $it->getEventObject();
|
||||
|
||||
// We need to check from these expanded alarms, which
|
||||
// one is the first to trigger. Based on this, we can
|
||||
// determine if we can 'give up' expanding events.
|
||||
$firstAlarm = null;
|
||||
if ($expandedEvent->VALARM !== null) {
|
||||
foreach($expandedEvent->VALARM as $expandedAlarm) {
|
||||
|
||||
$effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime();
|
||||
if ($expandedAlarm->isInTimeRange($start, $end)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((string)$expandedAlarm->TRIGGER['VALUE'] === 'DATE-TIME') {
|
||||
// This is an alarm with a non-relative trigger
|
||||
// time, likely created by a buggy client. The
|
||||
// implication is that every alarm in this
|
||||
// recurring event trigger at the exact same
|
||||
// time. It doesn't make sense to traverse
|
||||
// further.
|
||||
} else {
|
||||
// We store the first alarm as a means to
|
||||
// figure out when we can stop traversing.
|
||||
if (!$firstAlarm || $effectiveTrigger < $firstAlarm) {
|
||||
$firstAlarm = $effectiveTrigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_null($firstAlarm)) {
|
||||
// No alarm was found.
|
||||
//
|
||||
// Or technically: No alarm that will change for
|
||||
// every instance of the recurrence was found,
|
||||
// which means we can assume there was no match.
|
||||
return false;
|
||||
}
|
||||
if ($firstAlarm > $end) {
|
||||
return false;
|
||||
}
|
||||
$it->next();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return $component->isInTimeRange($start, $end);
|
||||
}
|
||||
|
||||
case 'VFREEBUSY' :
|
||||
throw new \Sabre\DAV\Exception\NotImplemented('time-range filters are currently not supported on ' . $component->name . ' components');
|
||||
|
||||
case 'COMPLETED' :
|
||||
case 'CREATED' :
|
||||
case 'DTEND' :
|
||||
case 'DTSTAMP' :
|
||||
case 'DTSTART' :
|
||||
case 'DUE' :
|
||||
case 'LAST-MODIFIED' :
|
||||
return ($start <= $component->getDateTime() && $end >= $component->getDateTime());
|
||||
|
||||
|
||||
|
||||
default :
|
||||
throw new \Sabre\DAV\Exception\BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
77
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarRootNode.php
vendored
Normal file
77
vendor/sabre/dav/lib/Sabre/CalDAV/CalendarRootNode.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\DAVACL\PrincipalBackend;
|
||||
|
||||
/**
|
||||
* Calendars collection
|
||||
*
|
||||
* This object is responsible for generating a list of calendar-homes for each
|
||||
* user.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class CalendarRootNode extends \Sabre\DAVACL\AbstractPrincipalCollection {
|
||||
|
||||
/**
|
||||
* CalDAV backend
|
||||
*
|
||||
* @var Sabre\CalDAV\Backend\BackendInterface
|
||||
*/
|
||||
protected $caldavBackend;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* This constructor needs both an authentication and a caldav backend.
|
||||
*
|
||||
* By default this class will show a list of calendar collections for
|
||||
* principals in the 'principals' collection. If your main principals are
|
||||
* actually located in a different path, use the $principalPrefix argument
|
||||
* to override this.
|
||||
*
|
||||
* @param PrincipalBackend\BackendInterface $principalBackend
|
||||
* @param Backend\BackendInterface $caldavBackend
|
||||
* @param string $principalPrefix
|
||||
*/
|
||||
public function __construct(PrincipalBackend\BackendInterface $principalBackend,Backend\BackendInterface $caldavBackend, $principalPrefix = 'principals') {
|
||||
|
||||
parent::__construct($principalBackend, $principalPrefix);
|
||||
$this->caldavBackend = $caldavBackend;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nodename
|
||||
*
|
||||
* We're overriding this, because the default will be the 'principalPrefix',
|
||||
* and we want it to be Sabre\CalDAV\Plugin::CALENDAR_ROOT
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return Plugin::CALENDAR_ROOT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a node for a principal.
|
||||
*
|
||||
* The passed array contains principal information, and is guaranteed to
|
||||
* at least contain a uri item. Other properties may or may not be
|
||||
* supplied by the authentication backend.
|
||||
*
|
||||
* @param array $principal
|
||||
* @return \Sabre\DAV\INode
|
||||
*/
|
||||
public function getChildForPrincipal(array $principal) {
|
||||
|
||||
return new UserCalendars($this->caldavBackend, $principal);
|
||||
|
||||
}
|
||||
|
||||
}
|
35
vendor/sabre/dav/lib/Sabre/CalDAV/Exception/InvalidComponentType.php
vendored
Normal file
35
vendor/sabre/dav/lib/Sabre/CalDAV/Exception/InvalidComponentType.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Exception;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* InvalidComponentType
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class InvalidComponentType extends DAV\Exception\Forbidden {
|
||||
|
||||
/**
|
||||
* Adds in extra information in the xml response.
|
||||
*
|
||||
* This method adds the {CALDAV:}supported-calendar-component as defined in rfc4791
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $errorNode
|
||||
* @return void
|
||||
*/
|
||||
public function serialize(DAV\Server $server, \DOMElement $errorNode) {
|
||||
|
||||
$doc = $errorNode->ownerDocument;
|
||||
|
||||
$np = $doc->createElementNS(CalDAV\Plugin::NS_CALDAV,'cal:supported-calendar-component');
|
||||
$errorNode->appendChild($np);
|
||||
|
||||
}
|
||||
|
||||
}
|
142
vendor/sabre/dav/lib/Sabre/CalDAV/ICSExportPlugin.php
vendored
Normal file
142
vendor/sabre/dav/lib/Sabre/CalDAV/ICSExportPlugin.php
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\VObject;
|
||||
|
||||
/**
|
||||
* ICS Exporter
|
||||
*
|
||||
* This plugin adds the ability to export entire calendars as .ics files.
|
||||
* This is useful for clients that don't support CalDAV yet. They often do
|
||||
* support ics files.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class ICSExportPlugin extends DAV\ServerPlugin {
|
||||
|
||||
/**
|
||||
* Reference to Server class
|
||||
*
|
||||
* @var \Sabre\DAV\Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* Initializes the plugin and registers event handlers
|
||||
*
|
||||
* @param \Sabre\DAV\Server $server
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(DAV\Server $server) {
|
||||
|
||||
$this->server = $server;
|
||||
$this->server->subscribeEvent('beforeMethod',array($this,'beforeMethod'), 90);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 'beforeMethod' event handles. This event handles intercepts GET requests ending
|
||||
* with ?export
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $uri
|
||||
* @return bool
|
||||
*/
|
||||
public function beforeMethod($method, $uri) {
|
||||
|
||||
if ($method!='GET') return;
|
||||
if ($this->server->httpRequest->getQueryString()!='export') return;
|
||||
|
||||
// splitting uri
|
||||
list($uri) = explode('?',$uri,2);
|
||||
|
||||
$node = $this->server->tree->getNodeForPath($uri);
|
||||
|
||||
if (!($node instanceof Calendar)) return;
|
||||
|
||||
// Checking ACL, if available.
|
||||
if ($aclPlugin = $this->server->getPlugin('acl')) {
|
||||
$aclPlugin->checkPrivileges($uri, '{DAV:}read');
|
||||
}
|
||||
|
||||
$this->server->httpResponse->setHeader('Content-Type','text/calendar');
|
||||
$this->server->httpResponse->sendStatus(200);
|
||||
|
||||
$nodes = $this->server->getPropertiesForPath($uri, array(
|
||||
'{' . Plugin::NS_CALDAV . '}calendar-data',
|
||||
),1);
|
||||
|
||||
$this->server->httpResponse->sendBody($this->generateICS($nodes));
|
||||
|
||||
// Returning false to break the event chain
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges all calendar objects, and builds one big ics export
|
||||
*
|
||||
* @param array $nodes
|
||||
* @return string
|
||||
*/
|
||||
public function generateICS(array $nodes) {
|
||||
|
||||
$calendar = new VObject\Component\VCalendar();
|
||||
$calendar->version = '2.0';
|
||||
if (DAV\Server::$exposeVersion) {
|
||||
$calendar->prodid = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN';
|
||||
} else {
|
||||
$calendar->prodid = '-//SabreDAV//SabreDAV//EN';
|
||||
}
|
||||
$calendar->calscale = 'GREGORIAN';
|
||||
|
||||
$collectedTimezones = array();
|
||||
|
||||
$timezones = array();
|
||||
$objects = array();
|
||||
|
||||
foreach($nodes as $node) {
|
||||
|
||||
if (!isset($node[200]['{' . Plugin::NS_CALDAV . '}calendar-data'])) {
|
||||
continue;
|
||||
}
|
||||
$nodeData = $node[200]['{' . Plugin::NS_CALDAV . '}calendar-data'];
|
||||
|
||||
$nodeComp = VObject\Reader::read($nodeData);
|
||||
|
||||
foreach($nodeComp->children() as $child) {
|
||||
|
||||
switch($child->name) {
|
||||
case 'VEVENT' :
|
||||
case 'VTODO' :
|
||||
case 'VJOURNAL' :
|
||||
$objects[] = $child;
|
||||
break;
|
||||
|
||||
// VTIMEZONE is special, because we need to filter out the duplicates
|
||||
case 'VTIMEZONE' :
|
||||
// Naively just checking tzid.
|
||||
if (in_array((string)$child->TZID, $collectedTimezones)) continue;
|
||||
|
||||
$timezones[] = $child;
|
||||
$collectedTimezones[] = $child->TZID;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach($timezones as $tz) $calendar->add($tz);
|
||||
foreach($objects as $obj) $calendar->add($obj);
|
||||
|
||||
return $calendar->serialize();
|
||||
|
||||
}
|
||||
|
||||
}
|
36
vendor/sabre/dav/lib/Sabre/CalDAV/ICalendar.php
vendored
Normal file
36
vendor/sabre/dav/lib/Sabre/CalDAV/ICalendar.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* Calendar interface
|
||||
*
|
||||
* Implement this interface to allow a node to be recognized as an calendar.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface ICalendar extends DAV\ICollection {
|
||||
|
||||
/**
|
||||
* Performs a calendar-query on the contents of this calendar.
|
||||
*
|
||||
* The calendar-query is defined in RFC4791 : CalDAV. Using the
|
||||
* calendar-query it is possible for a client to request a specific set of
|
||||
* object, based on contents of iCalendar properties, date-ranges and
|
||||
* iCalendar component types (VTODO, VEVENT).
|
||||
*
|
||||
* This method should just return a list of (relative) urls that match this
|
||||
* query.
|
||||
*
|
||||
* The list of filters are specified as an array. The exact array is
|
||||
* documented by \Sabre\CalDAV\CalendarQueryParser.
|
||||
*
|
||||
* @param array $filters
|
||||
* @return array
|
||||
*/
|
||||
public function calendarQuery(array $filters);
|
||||
|
||||
}
|
21
vendor/sabre/dav/lib/Sabre/CalDAV/ICalendarObject.php
vendored
Normal file
21
vendor/sabre/dav/lib/Sabre/CalDAV/ICalendarObject.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* CalendarObject interface
|
||||
*
|
||||
* Extend the ICalendarObject interface to allow your custom nodes to be picked up as
|
||||
* CalendarObjects.
|
||||
*
|
||||
* Calendar objects are resources such as Events, Todo's or Journals.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface ICalendarObject extends DAV\IFile {
|
||||
|
||||
}
|
||||
|
48
vendor/sabre/dav/lib/Sabre/CalDAV/IShareableCalendar.php
vendored
Normal file
48
vendor/sabre/dav/lib/Sabre/CalDAV/IShareableCalendar.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* This interface represents a Calendar that can be shared with other users.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface IShareableCalendar extends ICalendar {
|
||||
|
||||
/**
|
||||
* Updates the list of shares.
|
||||
*
|
||||
* The first array is a list of people that are to be added to the
|
||||
* calendar.
|
||||
*
|
||||
* Every element in the add array has the following properties:
|
||||
* * href - A url. Usually a mailto: address
|
||||
* * commonName - Usually a first and last name, or false
|
||||
* * summary - A description of the share, can also be false
|
||||
* * readOnly - A boolean value
|
||||
*
|
||||
* Every element in the remove array is just the address string.
|
||||
*
|
||||
* @param array $add
|
||||
* @param array $remove
|
||||
* @return void
|
||||
*/
|
||||
function updateShares(array $add, array $remove);
|
||||
|
||||
/**
|
||||
* Returns the list of people whom this calendar is shared with.
|
||||
*
|
||||
* Every element in this array should have the following properties:
|
||||
* * href - Often a mailto: address
|
||||
* * commonName - Optional, for example a first + last name
|
||||
* * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
|
||||
* * readOnly - boolean
|
||||
* * summary - Optional, a description for the share
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getShares();
|
||||
|
||||
}
|
36
vendor/sabre/dav/lib/Sabre/CalDAV/ISharedCalendar.php
vendored
Normal file
36
vendor/sabre/dav/lib/Sabre/CalDAV/ISharedCalendar.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* This interface represents a Calendar that is shared by a different user.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface ISharedCalendar extends ICalendar {
|
||||
|
||||
/**
|
||||
* This method should return the url of the owners' copy of the shared
|
||||
* calendar.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
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();
|
||||
|
||||
}
|
173
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Collection.php
vendored
Normal file
173
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Collection.php
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAVACL;
|
||||
|
||||
/**
|
||||
* This node represents a list of notifications.
|
||||
*
|
||||
* It provides no additional functionality, but you must implement this
|
||||
* interface to allow the Notifications plugin to mark the collection
|
||||
* as a notifications collection.
|
||||
*
|
||||
* This collection should only return Sabre\CalDAV\Notifications\INode nodes as
|
||||
* its children.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Collection extends DAV\Collection implements ICollection, DAVACL\IACL {
|
||||
|
||||
/**
|
||||
* The notification backend
|
||||
*
|
||||
* @var Sabre\CalDAV\Backend\NotificationSupport
|
||||
*/
|
||||
protected $caldavBackend;
|
||||
|
||||
/**
|
||||
* Principal uri
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $principalUri;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param CalDAV\Backend\NotificationSupport $caldavBackend
|
||||
* @param string $principalUri
|
||||
*/
|
||||
public function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri) {
|
||||
|
||||
$this->caldavBackend = $caldavBackend;
|
||||
$this->principalUri = $principalUri;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all notifications for a principal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getChildren() {
|
||||
|
||||
$children = array();
|
||||
$notifications = $this->caldavBackend->getNotificationsForPrincipal($this->principalUri);
|
||||
|
||||
foreach($notifications as $notification) {
|
||||
|
||||
$children[] = new Node(
|
||||
$this->caldavBackend,
|
||||
$this->principalUri,
|
||||
$notification
|
||||
);
|
||||
}
|
||||
|
||||
return $children;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return 'notifications';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner() {
|
||||
|
||||
return $this->principalUri;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getACL() {
|
||||
|
||||
return array(
|
||||
array(
|
||||
'principal' => $this->getOwner(),
|
||||
'privilege' => '{DAV:}read',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'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
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
24
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/ICollection.php
vendored
Normal file
24
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/ICollection.php
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications;
|
||||
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* This node represents a list of notifications.
|
||||
*
|
||||
* It provides no additional functionality, but you must implement this
|
||||
* interface to allow the Notifications plugin to mark the collection
|
||||
* as a notifications collection.
|
||||
*
|
||||
* This collection should only return Sabre\CalDAV\Notifications\INode nodes as
|
||||
* its children.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface ICollection extends DAV\ICollection {
|
||||
|
||||
|
||||
}
|
38
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/INode.php
vendored
Normal file
38
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/INode.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications;
|
||||
|
||||
/**
|
||||
* This node represents a single notification.
|
||||
*
|
||||
* The signature is mostly identical to that of Sabre\DAV\IFile, but the get() method
|
||||
* MUST return an xml document that matches the requirements of the
|
||||
* 'caldav-notifications.txt' spec.
|
||||
*
|
||||
* For a complete example, check out the Notification class, which contains
|
||||
* some helper functions.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface INode {
|
||||
|
||||
/**
|
||||
* This method must return an xml element, using the
|
||||
* Sabre\CalDAV\Notifications\INotificationType classes.
|
||||
*
|
||||
* @return INotificationType
|
||||
*/
|
||||
function getNotificationType();
|
||||
|
||||
/**
|
||||
* Returns the etag for the notification.
|
||||
*
|
||||
* The etag must be surrounded by litteral double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getETag();
|
||||
|
||||
}
|
44
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/INotificationType.php
vendored
Normal file
44
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/INotificationType.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications;
|
||||
use Sabre\DAV;
|
||||
|
||||
/**
|
||||
* This interface reflects a single notification type.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
interface INotificationType extends DAV\PropertyInterface {
|
||||
|
||||
/**
|
||||
* This method serializes the entire notification, as it is used in the
|
||||
* response body.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
function serializeBody(DAV\Server $server, \DOMElement $node);
|
||||
|
||||
/**
|
||||
* Returns a unique id for this notification
|
||||
*
|
||||
* This is just the base url. This should generally be some kind of unique
|
||||
* id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getId();
|
||||
|
||||
/**
|
||||
* Returns the ETag for this notification.
|
||||
*
|
||||
* The ETag must be surrounded by literal double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getETag();
|
||||
|
||||
}
|
192
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Node.php
vendored
Normal file
192
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Node.php
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\CalDAV;
|
||||
use Sabre\DAVACL;
|
||||
|
||||
/**
|
||||
* This node represents a single notification.
|
||||
*
|
||||
* The signature is mostly identical to that of Sabre\DAV\IFile, but the get() method
|
||||
* MUST return an xml document that matches the requirements of the
|
||||
* 'caldav-notifications.txt' spec.
|
||||
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Node extends DAV\File implements INode, DAVACL\IACL {
|
||||
|
||||
/**
|
||||
* The notification backend
|
||||
*
|
||||
* @var Sabre\CalDAV\Backend\NotificationSupport
|
||||
*/
|
||||
protected $caldavBackend;
|
||||
|
||||
/**
|
||||
* The actual notification
|
||||
*
|
||||
* @var Sabre\CalDAV\Notifications\INotificationType
|
||||
*/
|
||||
protected $notification;
|
||||
|
||||
/**
|
||||
* Owner principal of the notification
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $principalUri;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param CalDAV\Backend\NotificationSupport $caldavBackend
|
||||
* @param string $principalUri
|
||||
* @param CalDAV\Notifications\INotificationType $notification
|
||||
*/
|
||||
public function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri, INotificationType $notification) {
|
||||
|
||||
$this->caldavBackend = $caldavBackend;
|
||||
$this->principalUri = $principalUri;
|
||||
$this->notification = $notification;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path name for this notification
|
||||
*
|
||||
* @return id
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return $this->notification->getId() . '.xml';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the etag for the notification.
|
||||
*
|
||||
* The etag must be surrounded by litteral double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getETag() {
|
||||
|
||||
return $this->notification->getETag();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method must return an xml element, using the
|
||||
* Sabre\CalDAV\Notifications\INotificationType classes.
|
||||
*
|
||||
* @return INotificationType
|
||||
*/
|
||||
public function getNotificationType() {
|
||||
|
||||
return $this->notification;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this notification
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete() {
|
||||
|
||||
$this->caldavBackend->deleteNotification($this->getOwner(), $this->notification);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner() {
|
||||
|
||||
return $this->principalUri;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getACL() {
|
||||
|
||||
return array(
|
||||
array(
|
||||
'principal' => $this->getOwner(),
|
||||
'privilege' => '{DAV:}read',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'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
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
324
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Notification/Invite.php
vendored
Normal file
324
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Notification/Invite.php
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications\Notification;
|
||||
|
||||
use Sabre\CalDAV\SharingPlugin as SharingPlugin;
|
||||
use Sabre\DAV;
|
||||
use Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* This class represents the cs:invite-notification notification element.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class Invite extends DAV\Property implements CalDAV\Notifications\INotificationType {
|
||||
|
||||
/**
|
||||
* A unique id for the message
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* Timestamp of the notification
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $dtStamp;
|
||||
|
||||
/**
|
||||
* A url to the recipient of the notification. This can be an email
|
||||
* address (mailto:), or a principal url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $href;
|
||||
|
||||
/**
|
||||
* The type of message, see the SharingPlugin::STATUS_* constants.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* True if access to a calendar is read-only.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $readOnly;
|
||||
|
||||
/**
|
||||
* A url to the shared calendar.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $hostUrl;
|
||||
|
||||
/**
|
||||
* Url to the sharer of the calendar
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $organizer;
|
||||
|
||||
/**
|
||||
* The name of the sharer.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $commonName;
|
||||
|
||||
/**
|
||||
* The name of the sharer.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $firstName;
|
||||
|
||||
/**
|
||||
* The name of the sharer.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $lastName;
|
||||
|
||||
/**
|
||||
* A description of the share request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* The Etag for the notification
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $etag;
|
||||
|
||||
/**
|
||||
* The list of supported components
|
||||
*
|
||||
* @var Sabre\CalDAV\Property\SupportedCalendarComponentSet
|
||||
*/
|
||||
protected $supportedComponents;
|
||||
|
||||
/**
|
||||
* Creates the Invite notification.
|
||||
*
|
||||
* This constructor receives an array with the following elements:
|
||||
*
|
||||
* * id - A unique id
|
||||
* * etag - The etag
|
||||
* * dtStamp - A DateTime object with a timestamp for the notification.
|
||||
* * type - The type of notification, see SharingPlugin::STATUS_*
|
||||
* constants for details.
|
||||
* * readOnly - This must be set to true, if this is an invite for
|
||||
* read-only access to a calendar.
|
||||
* * hostUrl - A url to the shared calendar.
|
||||
* * organizer - Url to the sharer principal.
|
||||
* * commonName - The real name of the sharer (optional).
|
||||
* * firstName - The first name of the sharer (optional).
|
||||
* * lastName - The last name of the sharer (optional).
|
||||
* * summary - Description of the share, can be the same as the
|
||||
* calendar, but may also be modified (optional).
|
||||
* * supportedComponents - An instance of
|
||||
* Sabre\CalDAV\Property\SupportedCalendarComponentSet.
|
||||
* This allows the client to determine which components
|
||||
* will be supported in the shared calendar. This is
|
||||
* also optional.
|
||||
*
|
||||
* @param array $values All the options
|
||||
*/
|
||||
public function __construct(array $values) {
|
||||
|
||||
$required = array(
|
||||
'id',
|
||||
'etag',
|
||||
'href',
|
||||
'dtStamp',
|
||||
'type',
|
||||
'readOnly',
|
||||
'hostUrl',
|
||||
'organizer',
|
||||
);
|
||||
foreach($required as $item) {
|
||||
if (!isset($values[$item])) {
|
||||
throw new \InvalidArgumentException($item . ' is a required constructor option');
|
||||
}
|
||||
}
|
||||
|
||||
foreach($values as $key=>$value) {
|
||||
if (!property_exists($this, $key)) {
|
||||
throw new \InvalidArgumentException('Unknown option: ' . $key);
|
||||
}
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the notification as a single property.
|
||||
*
|
||||
* You should usually just encode the single top-level element of the
|
||||
* notification.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
public function serialize(DAV\Server $server, \DOMElement $node) {
|
||||
|
||||
$prop = $node->ownerDocument->createElement('cs:invite-notification');
|
||||
$node->appendChild($prop);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the entire notification, as it is used in the
|
||||
* response body.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
public function serializeBody(DAV\Server $server, \DOMElement $node) {
|
||||
|
||||
$doc = $node->ownerDocument;
|
||||
|
||||
$dt = $doc->createElement('cs:dtstamp');
|
||||
$this->dtStamp->setTimezone(new \DateTimezone('GMT'));
|
||||
$dt->appendChild($doc->createTextNode($this->dtStamp->format('Ymd\\THis\\Z')));
|
||||
$node->appendChild($dt);
|
||||
|
||||
$prop = $doc->createElement('cs:invite-notification');
|
||||
$node->appendChild($prop);
|
||||
|
||||
$uid = $doc->createElement('cs:uid');
|
||||
$uid->appendChild( $doc->createTextNode($this->id) );
|
||||
$prop->appendChild($uid);
|
||||
|
||||
$href = $doc->createElement('d:href');
|
||||
$href->appendChild( $doc->createTextNode( $this->href ) );
|
||||
$prop->appendChild($href);
|
||||
|
||||
$nodeName = null;
|
||||
switch($this->type) {
|
||||
|
||||
case SharingPlugin::STATUS_ACCEPTED :
|
||||
$nodeName = 'cs:invite-accepted';
|
||||
break;
|
||||
case SharingPlugin::STATUS_DECLINED :
|
||||
$nodeName = 'cs:invite-declined';
|
||||
break;
|
||||
case SharingPlugin::STATUS_DELETED :
|
||||
$nodeName = 'cs:invite-deleted';
|
||||
break;
|
||||
case SharingPlugin::STATUS_NORESPONSE :
|
||||
$nodeName = 'cs:invite-noresponse';
|
||||
break;
|
||||
|
||||
}
|
||||
$prop->appendChild(
|
||||
$doc->createElement($nodeName)
|
||||
);
|
||||
$hostHref = $doc->createElement('d:href', $server->getBaseUri() . $this->hostUrl);
|
||||
$hostUrl = $doc->createElement('cs:hosturl');
|
||||
$hostUrl->appendChild($hostHref);
|
||||
$prop->appendChild($hostUrl);
|
||||
|
||||
$access = $doc->createElement('cs:access');
|
||||
if ($this->readOnly) {
|
||||
$access->appendChild($doc->createElement('cs:read'));
|
||||
} else {
|
||||
$access->appendChild($doc->createElement('cs:read-write'));
|
||||
}
|
||||
$prop->appendChild($access);
|
||||
|
||||
$organizerUrl = $doc->createElement('cs:organizer');
|
||||
// If the organizer contains a 'mailto:' part, it means it should be
|
||||
// treated as absolute.
|
||||
if (strtolower(substr($this->organizer,0,7))==='mailto:') {
|
||||
$organizerHref = new DAV\Property\Href($this->organizer, false);
|
||||
} else {
|
||||
$organizerHref = new DAV\Property\Href($this->organizer, true);
|
||||
}
|
||||
$organizerHref->serialize($server, $organizerUrl);
|
||||
|
||||
if ($this->commonName) {
|
||||
$commonName = $doc->createElement('cs:common-name');
|
||||
$commonName->appendChild($doc->createTextNode($this->commonName));
|
||||
$organizerUrl->appendChild($commonName);
|
||||
|
||||
$commonNameOld = $doc->createElement('cs:organizer-cn');
|
||||
$commonNameOld->appendChild($doc->createTextNode($this->commonName));
|
||||
$prop->appendChild($commonNameOld);
|
||||
|
||||
}
|
||||
if ($this->firstName) {
|
||||
$firstName = $doc->createElement('cs:first-name');
|
||||
$firstName->appendChild($doc->createTextNode($this->firstName));
|
||||
$organizerUrl->appendChild($firstName);
|
||||
|
||||
$firstNameOld = $doc->createElement('cs:organizer-first');
|
||||
$firstNameOld->appendChild($doc->createTextNode($this->firstName));
|
||||
$prop->appendChild($firstNameOld);
|
||||
}
|
||||
if ($this->lastName) {
|
||||
$lastName = $doc->createElement('cs:last-name');
|
||||
$lastName->appendChild($doc->createTextNode($this->lastName));
|
||||
$organizerUrl->appendChild($lastName);
|
||||
|
||||
$lastNameOld = $doc->createElement('cs:organizer-last');
|
||||
$lastNameOld->appendChild($doc->createTextNode($this->lastName));
|
||||
$prop->appendChild($lastNameOld);
|
||||
}
|
||||
$prop->appendChild($organizerUrl);
|
||||
|
||||
if ($this->summary) {
|
||||
$summary = $doc->createElement('cs:summary');
|
||||
$summary->appendChild($doc->createTextNode($this->summary));
|
||||
$prop->appendChild($summary);
|
||||
}
|
||||
if ($this->supportedComponents) {
|
||||
|
||||
$xcomp = $doc->createElement('cal:supported-calendar-component-set');
|
||||
$this->supportedComponents->serialize($server, $xcomp);
|
||||
$prop->appendChild($xcomp);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique id for this notification
|
||||
*
|
||||
* This is just the base url. This should generally be some kind of unique
|
||||
* id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId() {
|
||||
|
||||
return $this->id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ETag for this notification.
|
||||
*
|
||||
* The ETag must be surrounded by literal double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getETag() {
|
||||
|
||||
return $this->etag;
|
||||
|
||||
}
|
||||
|
||||
}
|
218
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Notification/InviteReply.php
vendored
Normal file
218
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Notification/InviteReply.php
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications\Notification;
|
||||
|
||||
use Sabre\CalDAV\SharingPlugin as SharingPlugin;
|
||||
use Sabre\DAV;
|
||||
use Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* This class represents the cs:invite-reply notification element.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class InviteReply extends DAV\Property implements CalDAV\Notifications\INotificationType {
|
||||
|
||||
/**
|
||||
* A unique id for the message
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* Timestamp of the notification
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $dtStamp;
|
||||
|
||||
/**
|
||||
* The unique id of the notification this was a reply to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $inReplyTo;
|
||||
|
||||
/**
|
||||
* A url to the recipient of the original (!) notification.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $href;
|
||||
|
||||
/**
|
||||
* The type of message, see the SharingPlugin::STATUS_ constants.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* A url to the shared calendar.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $hostUrl;
|
||||
|
||||
/**
|
||||
* A description of the share request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $summary;
|
||||
|
||||
/**
|
||||
* Notification Etag
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $etag;
|
||||
|
||||
/**
|
||||
* Creates the Invite Reply Notification.
|
||||
*
|
||||
* This constructor receives an array with the following elements:
|
||||
*
|
||||
* * id - A unique id
|
||||
* * etag - The etag
|
||||
* * dtStamp - A DateTime object with a timestamp for the notification.
|
||||
* * inReplyTo - This should refer to the 'id' of the notification
|
||||
* this is a reply to.
|
||||
* * type - The type of notification, see SharingPlugin::STATUS_*
|
||||
* constants for details.
|
||||
* * hostUrl - A url to the shared calendar.
|
||||
* * summary - Description of the share, can be the same as the
|
||||
* calendar, but may also be modified (optional).
|
||||
*/
|
||||
public function __construct(array $values) {
|
||||
|
||||
$required = array(
|
||||
'id',
|
||||
'etag',
|
||||
'href',
|
||||
'dtStamp',
|
||||
'inReplyTo',
|
||||
'type',
|
||||
'hostUrl',
|
||||
);
|
||||
foreach($required as $item) {
|
||||
if (!isset($values[$item])) {
|
||||
throw new \InvalidArgumentException($item . ' is a required constructor option');
|
||||
}
|
||||
}
|
||||
|
||||
foreach($values as $key=>$value) {
|
||||
if (!property_exists($this, $key)) {
|
||||
throw new \InvalidArgumentException('Unknown option: ' . $key);
|
||||
}
|
||||
$this->$key = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the notification as a single property.
|
||||
*
|
||||
* You should usually just encode the single top-level element of the
|
||||
* notification.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
public function serialize(DAV\Server $server, \DOMElement $node) {
|
||||
|
||||
$prop = $node->ownerDocument->createElement('cs:invite-reply');
|
||||
$node->appendChild($prop);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the entire notification, as it is used in the
|
||||
* response body.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
public function serializeBody(DAV\Server $server, \DOMElement $node) {
|
||||
|
||||
$doc = $node->ownerDocument;
|
||||
|
||||
$dt = $doc->createElement('cs:dtstamp');
|
||||
$this->dtStamp->setTimezone(new \DateTimezone('GMT'));
|
||||
$dt->appendChild($doc->createTextNode($this->dtStamp->format('Ymd\\THis\\Z')));
|
||||
$node->appendChild($dt);
|
||||
|
||||
$prop = $doc->createElement('cs:invite-reply');
|
||||
$node->appendChild($prop);
|
||||
|
||||
$uid = $doc->createElement('cs:uid');
|
||||
$uid->appendChild($doc->createTextNode($this->id));
|
||||
$prop->appendChild($uid);
|
||||
|
||||
$inReplyTo = $doc->createElement('cs:in-reply-to');
|
||||
$inReplyTo->appendChild( $doc->createTextNode($this->inReplyTo) );
|
||||
$prop->appendChild($inReplyTo);
|
||||
|
||||
$href = $doc->createElement('d:href');
|
||||
$href->appendChild( $doc->createTextNode($this->href) );
|
||||
$prop->appendChild($href);
|
||||
|
||||
$nodeName = null;
|
||||
switch($this->type) {
|
||||
|
||||
case SharingPlugin::STATUS_ACCEPTED :
|
||||
$nodeName = 'cs:invite-accepted';
|
||||
break;
|
||||
case SharingPlugin::STATUS_DECLINED :
|
||||
$nodeName = 'cs:invite-declined';
|
||||
break;
|
||||
|
||||
}
|
||||
$prop->appendChild(
|
||||
$doc->createElement($nodeName)
|
||||
);
|
||||
$hostHref = $doc->createElement('d:href', $server->getBaseUri() . $this->hostUrl);
|
||||
$hostUrl = $doc->createElement('cs:hosturl');
|
||||
$hostUrl->appendChild($hostHref);
|
||||
$prop->appendChild($hostUrl);
|
||||
|
||||
if ($this->summary) {
|
||||
$summary = $doc->createElement('cs:summary');
|
||||
$summary->appendChild($doc->createTextNode($this->summary));
|
||||
$prop->appendChild($summary);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique id for this notification
|
||||
*
|
||||
* This is just the base url. This should generally be some kind of unique
|
||||
* id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId() {
|
||||
|
||||
return $this->id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ETag for this notification.
|
||||
*
|
||||
* The ETag must be surrounded by literal double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getETag() {
|
||||
|
||||
return $this->etag;
|
||||
|
||||
}
|
||||
}
|
182
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Notification/SystemStatus.php
vendored
Normal file
182
vendor/sabre/dav/lib/Sabre/CalDAV/Notifications/Notification/SystemStatus.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace Sabre\CalDAV\Notifications\Notification;
|
||||
|
||||
use Sabre\DAV;
|
||||
use Sabre\CalDAV;
|
||||
|
||||
/**
|
||||
* SystemStatus notification
|
||||
*
|
||||
* This notification can be used to indicate to the user that the system is
|
||||
* down.
|
||||
*
|
||||
* @copyright Copyright (C) 2007-2013 fruux GmbH (https://fruux.com/).
|
||||
* @author Evert Pot (http://evertpot.com/)
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class SystemStatus extends DAV\Property implements CalDAV\Notifications\INotificationType {
|
||||
|
||||
const TYPE_LOW = 1;
|
||||
const TYPE_MEDIUM = 2;
|
||||
const TYPE_HIGH = 3;
|
||||
|
||||
/**
|
||||
* A unique id
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* The type of alert. This should be one of the TYPE_ constants.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* A human-readable description of the problem.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* A url to a website with more information for the user.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $href;
|
||||
|
||||
/**
|
||||
* Notification Etag
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $etag;
|
||||
|
||||
/**
|
||||
* Creates the notification.
|
||||
*
|
||||
* Some kind of unique id should be provided. This is used to generate a
|
||||
* url.
|
||||
*
|
||||
* @param string $id
|
||||
* @param string $etag
|
||||
* @param int $type
|
||||
* @param string $description
|
||||
* @param string $href
|
||||
*/
|
||||
public function __construct($id, $etag, $type = self::TYPE_HIGH, $description = null, $href = null) {
|
||||
|
||||
$this->id = $id;
|
||||
$this->type = $type;
|
||||
$this->description = $description;
|
||||
$this->href = $href;
|
||||
$this->etag = $etag;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the notification as a single property.
|
||||
*
|
||||
* You should usually just encode the single top-level element of the
|
||||
* notification.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
public function serialize(DAV\Server $server, \DOMElement $node) {
|
||||
|
||||
switch($this->type) {
|
||||
case self::TYPE_LOW :
|
||||
$type = 'low';
|
||||
break;
|
||||
case self::TYPE_MEDIUM :
|
||||
$type = 'medium';
|
||||
break;
|
||||
default :
|
||||
case self::TYPE_HIGH :
|
||||
$type = 'high';
|
||||
break;
|
||||
}
|
||||
|
||||
$prop = $node->ownerDocument->createElement('cs:systemstatus');
|
||||
$prop->setAttribute('type', $type);
|
||||
|
||||
$node->appendChild($prop);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method serializes the entire notification, as it is used in the
|
||||
* response body.
|
||||
*
|
||||
* @param DAV\Server $server
|
||||
* @param \DOMElement $node
|
||||
* @return void
|
||||
*/
|
||||
public function serializeBody(DAV\Server $server, \DOMElement $node) {
|
||||
|
||||
switch($this->type) {
|
||||
case self::TYPE_LOW :
|
||||
$type = 'low';
|
||||
break;
|
||||
case self::TYPE_MEDIUM :
|
||||
$type = 'medium';
|
||||
break;
|
||||
default :
|
||||
case self::TYPE_HIGH :
|
||||
$type = 'high';
|
||||
break;
|
||||
}
|
||||
|
||||
$prop = $node->ownerDocument->createElement('cs:systemstatus');
|
||||
$prop->setAttribute('type', $type);
|
||||
|
||||
if ($this->description) {
|
||||
$text = $node->ownerDocument->createTextNode($this->description);
|
||||
$desc = $node->ownerDocument->createElement('cs:description');
|
||||
$desc->appendChild($text);
|
||||
$prop->appendChild($desc);
|
||||
}
|
||||
if ($this->href) {
|
||||
$text = $node->ownerDocument->createTextNode($this->href);
|
||||
$href = $node->ownerDocument->createElement('d:href');
|
||||
$href->appendChild($text);
|
||||
$prop->appendChild($href);
|
||||
}
|
||||
|
||||
$node->appendChild($prop);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique id for this notification
|
||||
*
|
||||
* This is just the base url. This should generally be some kind of unique
|
||||
* id.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId() {
|
||||
|
||||
return $this->id;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the ETag for this notification.
|
||||
*
|
||||
* The ETag must be surrounded by literal double-quotes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getETag() {
|
||||
|
||||
return $this->etag;
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user